/*========================================================================= Program: CMake - Cross-Platform Makefile Generator Module: $RCSfile: cmCPackTarCompressGenerator.cxx,v $ Language: C++ Date: $Date: 2007-07-31 02:51:21 $ Version: $Revision: 1.9 $ Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "cmCPackTarCompressGenerator.h" #include "cmake.h" #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmSystemTools.h" #include "cmMakefile.h" #include "cmGeneratedFileStream.h" #include "cmCPackLog.h" #include #include #include #include // auto_ptr #include #include //---------------------------------------------------------------------- class cmCPackTarCompressGeneratorForward { public: static int GenerateHeader(cmCPackTarCompressGenerator* gg, std::ostream* os) { return gg->GenerateHeader(os); } }; //---------------------------------------------------------------------- cmCPackTarCompressGenerator::cmCPackTarCompressGenerator() { } //---------------------------------------------------------------------- cmCPackTarCompressGenerator::~cmCPackTarCompressGenerator() { } //---------------------------------------------------------------------- class cmCPackTarCompress_Data { public: cmCPackTarCompress_Data(cmCPackTarCompressGenerator* gen) : OutputStream(0), Generator(gen) {} std::ostream* OutputStream; cmCPackTarCompressGenerator* Generator; cmcompress_stream CMCompressStream; }; //---------------------------------------------------------------------- extern "C" { // For cmTar int cmCPackTarCompress_Data_Open(void *client_data, const char* name, int oflags, mode_t mode); ssize_t cmCPackTarCompress_Data_Write(void *client_data, void *buff, size_t n); int cmCPackTarCompress_Data_Close(void *client_data); // For cmCompress int cmCPackTarCompress_Compress_Output(void* cdata, const char* data, int len); } //---------------------------------------------------------------------- int cmCPackTarCompress_Data_Open(void *client_data, const char* pathname, int, mode_t) { cmCPackTarCompress_Data *mydata = (cmCPackTarCompress_Data*)client_data; if ( !cmcompress_compress_initialize(&mydata->CMCompressStream) ) { return -1; } mydata->CMCompressStream.client_data = mydata; mydata->CMCompressStream.output_stream = cmCPackTarCompress_Compress_Output; cmGeneratedFileStream* gf = new cmGeneratedFileStream; // Open binary gf->Open(pathname, false, true); mydata->OutputStream = gf; if ( !*mydata->OutputStream ) { return -1; } if ( !cmcompress_compress_start(&mydata->CMCompressStream) ) { return -1; } if ( !cmCPackTarCompressGeneratorForward::GenerateHeader( mydata->Generator,gf)) { return -1; } return 0; } //---------------------------------------------------------------------- ssize_t cmCPackTarCompress_Data_Write(void *client_data, void *buff, size_t n) { cmCPackTarCompress_Data *mydata = (cmCPackTarCompress_Data*)client_data; if ( !cmcompress_compress(&mydata->CMCompressStream, buff, n) ) { return 0; } return n; } //---------------------------------------------------------------------- int cmCPackTarCompress_Data_Close(void *client_data) { cmCPackTarCompress_Data *mydata = (cmCPackTarCompress_Data*)client_data; if ( !cmcompress_compress_finalize(&mydata->CMCompressStream) ) { delete mydata->OutputStream; return -1; } delete mydata->OutputStream; mydata->OutputStream = 0; return (0); } //---------------------------------------------------------------------- int cmCPackTarCompressGenerator::InitializeInternal() { this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1"); return this->Superclass::InitializeInternal(); } //---------------------------------------------------------------------- int cmCPackTarCompressGenerator::CompressFiles(const char* outFileName, const char* toplevel, const std::vector& files) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << (toplevel ? toplevel : "(NULL)") << std::endl); cmCPackTarCompress_Data mydata(this); TAR *t; char buf[TAR_MAXPATHLEN]; char pathname[TAR_MAXPATHLEN]; tartype_t compressType = { (openfunc_t)cmCPackTarCompress_Data_Open, (closefunc_t)cmCPackTarCompress_Data_Close, (readfunc_t)0, (writefunc_t)cmCPackTarCompress_Data_Write, &mydata }; // Ok, this libtar is not const safe. for now use auto_ptr hack char* realName = new char[ strlen(outFileName) + 1 ]; std::auto_ptr realNamePtr(realName); strcpy(realName, outFileName); int flags = O_WRONLY | O_CREAT; int options = 0; if(this->GeneratorVerbose) { options |= TAR_VERBOSE; } #ifdef __CYGWIN__ options |= TAR_GNU; #endif if (tar_open(&t, realName, &compressType, flags, 0644, options) == -1) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_open(): " << strerror(errno) << std::endl); return 0; } std::vector::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, rp.c_str(), sizeof(buf)); buf[sizeof(buf)-1] = 0; if (tar_append_tree(t, pathname, buf) != 0) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_append_tree(\"" << buf << "\", \"" << pathname << "\"): " << strerror(errno) << std::endl); tar_close(t); return 0; } } if (tar_append_eof(t) != 0) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_append_eof(): " << strerror(errno) << std::endl); tar_close(t); return 0; } if (tar_close(t) != 0) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_close(): " << strerror(errno) << std::endl); return 0; } return 1; } //---------------------------------------------------------------------- int cmCPackTarCompress_Compress_Output(void* client_data, const char* data, int data_length) { if(!client_data) { return 0; } cmcompress_stream *cstream = static_cast(client_data); cmCPackTarCompress_Data *mydata = static_cast(cstream->client_data); if ( !mydata->OutputStream ) { return 0; } mydata->OutputStream->write(data, data_length); return data_length; } //---------------------------------------------------------------------- int cmCPackTarCompressGenerator::GenerateHeader(std::ostream* os) { (void)os; return 1; }