diff options
Diffstat (limited to 'Source/CPack/cmCPackTGZGenerator.cxx')
-rw-r--r-- | Source/CPack/cmCPackTGZGenerator.cxx | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/Source/CPack/cmCPackTGZGenerator.cxx b/Source/CPack/cmCPackTGZGenerator.cxx index d4d8d96..edbb483 100644 --- a/Source/CPack/cmCPackTGZGenerator.cxx +++ b/Source/CPack/cmCPackTGZGenerator.cxx @@ -26,7 +26,7 @@ #include "cmCPackLog.h" #include <cmsys/SystemTools.hxx> -#include <cmzlib/zlib.h> +#include <cmzlib/zutil.h> #include <libtar/libtar.h> #include <memory> // auto_ptr #include <fcntl.h> @@ -52,15 +52,21 @@ cmCPackTGZGenerator::~cmCPackTGZGenerator() { } +static const size_t cmCPackTGZ_Data_BlockSize = 16384; + //---------------------------------------------------------------------- class cmCPackTGZ_Data { public: cmCPackTGZ_Data(cmCPackTGZGenerator* gen) : - Name(0), OutputStream(0), Generator(gen) {} + Name(0), OutputStream(0), Generator(gen), m_CompressionLevel(Z_DEFAULT_COMPRESSION) {} const char *Name; std::ostream* OutputStream; cmCPackTGZGenerator* Generator; + char m_CompressedBuffer[cmCPackTGZ_Data_BlockSize]; + int m_CompressionLevel; + z_stream m_ZLibStream; + uLong m_CRC; }; //---------------------------------------------------------------------- @@ -76,6 +82,16 @@ int cmCPackTGZ_Data_Open(void *client_data, const char* pathname, int, mode_t) { cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data; + mydata->m_ZLibStream.zalloc = Z_NULL; + mydata->m_ZLibStream.zfree = Z_NULL; + mydata->m_ZLibStream.opaque = Z_NULL; + int strategy = Z_DEFAULT_STRATEGY; + if ( deflateInit2(&mydata->m_ZLibStream, mydata->m_CompressionLevel, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy) != Z_OK ) + { + return -1; + } + cmGeneratedFileStream* gf = new cmGeneratedFileStream(pathname); mydata->OutputStream = gf; if ( !*mydata->OutputStream ) @@ -83,13 +99,15 @@ int cmCPackTGZ_Data_Open(void *client_data, const char* pathname, int, mode_t) return -1; } - gf->SetCompression(true); - gf->SetCompressionExtraExtension(false); + gf->SetCompression(false); if ( !cmCPackTGZGeneratorForward::GenerateHeader(mydata->Generator,gf)) { return -1; } + + mydata->m_CRC = crc32(0L, Z_NULL, 0); + return 0; } @@ -98,11 +116,28 @@ ssize_t cmCPackTGZ_Data_Write(void *client_data, void *buff, size_t n) { cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data; - mydata->OutputStream->write(reinterpret_cast<const char*>(buff), n); + mydata->m_ZLibStream.avail_in = n; + mydata->m_ZLibStream.next_in = reinterpret_cast<Bytef*>(buff); + + do { + mydata->m_ZLibStream.avail_out = cmCPackTGZ_Data_BlockSize; + mydata->m_ZLibStream.next_out = reinterpret_cast<Bytef*>(mydata->m_CompressedBuffer); + int ret = deflate(&mydata->m_ZLibStream, (n?Z_NO_FLUSH:Z_FINISH)); /* no bad return value */ + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + + size_t compressedSize = cmCPackTGZ_Data_BlockSize - mydata->m_ZLibStream.avail_out; + + mydata->OutputStream->write(reinterpret_cast<const char*>(mydata->m_CompressedBuffer), compressedSize); + } while ( mydata->m_ZLibStream.avail_out == 0 ); + if ( !*mydata->OutputStream ) { return 0; } + if ( n ) + { + mydata->m_CRC = crc32(mydata->m_CRC, reinterpret_cast<Bytef *>(buff), n); + } return n; } @@ -111,6 +146,23 @@ int cmCPackTGZ_Data_Close(void *client_data) { cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data; + cmCPackTGZ_Data_Write(client_data, 0, 0); + + char buffer[8]; + int n; + uLong x = mydata->m_CRC; + for (n = 0; n < 4; n++) { + buffer[n] = (int)(x & 0xff); + x >>= 8; + } + x = mydata->m_ZLibStream.total_in; + for (n = 0; n < 4; n++) { + buffer[n+4] = (int)(x & 0xff); + x >>= 8; + } + + mydata->OutputStream->write(buffer, 8); + (void)deflateEnd(&mydata->m_ZLibStream); delete mydata->OutputStream; mydata->OutputStream = 0; return (0); @@ -152,11 +204,12 @@ int cmCPackTGZGenerator::CompressFiles(const char* outFileName, const char* topl std::vector<std::string>::const_iterator fileIt; for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt ) { + std::string rp = cmSystemTools::RelativePath(toplevel, fileIt->c_str()); strncpy(pathname, fileIt->c_str(), sizeof(pathname)); pathname[sizeof(pathname)-1] = 0; - strncpy(buf, pathname, sizeof(buf)); + strncpy(buf, rp.c_str(), sizeof(buf)); buf[sizeof(buf)-1] = 0; - if (tar_append_tree(t, buf, pathname) != 0) + if (tar_append_tree(t, pathname, buf) != 0) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_append_tree(\"" << buf << "\", \"" << pathname << "\"): " @@ -183,7 +236,11 @@ int cmCPackTGZGenerator::CompressFiles(const char* outFileName, const char* topl //---------------------------------------------------------------------- int cmCPackTGZGenerator::GenerateHeader(std::ostream* os) { - (void)os; + const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + char header[10]; + sprintf(header, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + os->write(header, 10); return 1; } |