diff options
author | Bill Hoffman <bill.hoffman@kitware.com> | 2009-10-30 17:10:56 (GMT) |
---|---|---|
committer | Bill Hoffman <bill.hoffman@kitware.com> | 2009-10-30 17:10:56 (GMT) |
commit | fb51d98562a26b6dcde7d3597938a0b707b6b881 (patch) | |
tree | b42fbfb6b27b7a9e2d5068601f61d80e7033dc79 /Source | |
parent | 0615218bdf3e240e44e539f9eed6c1cf9fbff2d4 (diff) | |
download | CMake-fb51d98562a26b6dcde7d3597938a0b707b6b881.zip CMake-fb51d98562a26b6dcde7d3597938a0b707b6b881.tar.gz CMake-fb51d98562a26b6dcde7d3597938a0b707b6b881.tar.bz2 |
Switch to using libarchive from libtar for cpack and cmake -E tar
This allows for a built in bzip and zip capability, so external tools
will not be needed for these packagers. The cmake -E tar xf should be
able to handle all compression types now as well.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CMakeLists.txt | 5 | ||||
-rw-r--r-- | Source/CPack/cmCPackArchiveGenerator.cxx | 230 | ||||
-rw-r--r-- | Source/CPack/cmCPackArchiveGenerator.h | 47 | ||||
-rw-r--r-- | Source/CPack/cmCPackTGZGenerator.cxx | 272 | ||||
-rw-r--r-- | Source/CPack/cmCPackTGZGenerator.h | 18 | ||||
-rw-r--r-- | Source/CPack/cmCPackTarBZip2Generator.cxx | 156 | ||||
-rw-r--r-- | Source/CPack/cmCPackTarBZip2Generator.h | 14 | ||||
-rw-r--r-- | Source/CPack/cmCPackTarCompressGenerator.cxx | 231 | ||||
-rw-r--r-- | Source/CPack/cmCPackTarCompressGenerator.h | 12 | ||||
-rw-r--r-- | Source/CPack/cmCPackZIPGenerator.cxx | 76 | ||||
-rw-r--r-- | Source/CPack/cmCPackZIPGenerator.h | 14 | ||||
-rw-r--r-- | Source/cmSystemTools.cxx | 567 |
12 files changed, 615 insertions, 1027 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 9099691..96b0e4e 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -325,10 +325,10 @@ ENDIF (WIN32) # create a library used by the command line and the GUI ADD_LIBRARY(CMakeLib ${SRCS}) -TARGET_LINK_LIBRARIES(CMakeLib cmsys +TARGET_LINK_LIBRARIES(CMakeLib cmsys ${CMAKE_EXPAT_LIBRARIES} ${CMAKE_ZLIB_LIBRARIES} ${CMAKE_TAR_LIBRARIES} ${CMAKE_COMPRESS_LIBRARIES} - ${CMAKE_CURL_LIBRARIES}) + ${CMAKE_CURL_LIBRARIES} ) # On Apple we need Carbon IF(APPLE) @@ -405,6 +405,7 @@ TARGET_LINK_LIBRARIES(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES} ${CMAKE_XMLRPC_L # Sources for CPack # SET(CPACK_SRCS + CPack/cmCPackArchiveGenerator.cxx CPack/cmCPackComponentGroup.cxx CPack/cmCPackGeneratorFactory.cxx CPack/cmCPackGenerator.cxx diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx new file mode 100644 index 0000000..b11670c --- /dev/null +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -0,0 +1,230 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmCPackArchiveGenerator.h" + +#include "cmake.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" +#include "cmSystemTools.h" +#include "cmMakefile.h" +#include "cmGeneratedFileStream.h" +#include "cmCPackLog.h" +#include <errno.h> + +#include <cmsys/SystemTools.hxx> +#include <cmlibarchive/libarchive/archive.h> +#include <cmlibarchive/libarchive/archive_entry.h> + + +//---------------------------------------------------------------------- +cmCPackArchiveGenerator::cmCPackArchiveGenerator(CompressType t, + ArchiveType at) +{ + this->Compress = t; + this->Archive = at; +} + +//---------------------------------------------------------------------- +cmCPackArchiveGenerator::~cmCPackArchiveGenerator() +{ +} + +static const size_t cmCPackTGZ_Data_BlockSize = 16384; + +// make this an anonymous namespace so that archive.h does not +// have to be included in the .h file for this class +namespace +{ +bool SetArchiveType(struct archive* a, + cmCPackArchiveGenerator::CompressType ct, + cmCPackArchiveGenerator::ArchiveType at) +{ + // pick a compression type + int res; + switch(ct) + { + case cmCPackArchiveGenerator::GZIP: + res = archive_write_set_compression_gzip(a); + break; + case cmCPackArchiveGenerator::BZIP2: + res = archive_write_set_compression_bzip2(a); + break; + case cmCPackArchiveGenerator::COMPRESS: + res = archive_write_set_compression_compress(a); + break; + case cmCPackArchiveGenerator::LZMA: + res = archive_write_set_compression_lzma(a); + break; + case cmCPackArchiveGenerator::NONE: + default: + res = archive_write_set_compression_none(a); + } + if(res != ARCHIVE_OK) + { + return false; + } + // pick the archive type + switch(at) + { + case cmCPackArchiveGenerator::TAR: + // maybe this: + // archive_write_set_format_pax(a); + res = archive_write_set_format_ustar(a); // is this what we want? + break; + case cmCPackArchiveGenerator::ZIP: + res = archive_write_set_format_zip(a); + break; + } + if(res != ARCHIVE_OK) + { + return false; + } + return true; +} + +struct StreamData +{ + StreamData(cmGeneratedFileStream* gfs, + cmCPackArchiveGenerator* ag) + { + this->GeneratedFileStream = gfs; + this->Generator = ag; + } + cmGeneratedFileStream* GeneratedFileStream; + cmCPackArchiveGenerator* Generator; +}; + + +extern "C" +{ +int OpenArchive(struct archive *a, void *client_data) +{ + struct StreamData *data = (StreamData*)client_data; + if(data->GeneratedFileStream && + data->GeneratedFileStream->is_open()) + { + if(data->Generator-> + GenerateHeader(data->GeneratedFileStream)) + { + return ARCHIVE_OK; + } + } + return (ARCHIVE_FATAL); +} + +__LA_SSIZE_T WriteArchive(struct archive *a, + void *client_data, + const void *buff, + size_t n) +{ + struct StreamData *data = (StreamData*)client_data; + data->GeneratedFileStream-> + write(reinterpret_cast<const char*>(buff),n); + if(!data->GeneratedFileStream->bad()) + { + return n; + } + return 0; +} + + +int CloseArchive(struct archive *a, void *client_data) +{ + struct StreamData *data = (StreamData*)client_data; + if(data->GeneratedFileStream->Close()) + { + delete data->GeneratedFileStream; + return ARCHIVE_OK; + } + return ARCHIVE_FATAL; +} +} //extern C +} // anon name space + + +//---------------------------------------------------------------------- +int cmCPackArchiveGenerator::InitializeInternal() +{ + this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1"); + return this->Superclass::InitializeInternal(); +} + +int cmCPackArchiveGenerator::CompressFiles(const char* outFileName, + const char* toplevel, const std::vector<std::string>& files) +{ + cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " + << (toplevel ? toplevel : "(NULL)") << std::endl); + // create a new archive + struct archive* a = archive_write_new(); + // Set the compress and archive types for the archive + SetArchiveType(a, this->Compress, this->Archive); + // Open binary stream + cmGeneratedFileStream* gf = new cmGeneratedFileStream; + gf->Open(outFileName, false, true); + StreamData data(gf, this); + // pass callbacks to archive_write_open to handle stream + archive_write_open(a, + &data, + OpenArchive, + WriteArchive, + CloseArchive); + // create a new disk struct + struct archive* disk = archive_read_disk_new(); + archive_read_disk_set_standard_lookup(disk); + std::vector<std::string>::const_iterator fileIt; + for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt ) + { + // create a new entry for each file + struct archive_entry *entry = archive_entry_new(); + // Get the relative path to the file + std::string rp = cmSystemTools::RelativePath(toplevel, fileIt->c_str()); + // Set the name of the entry to the file name + archive_entry_set_pathname(entry, rp.c_str()); + // get the information about the file from stat + struct stat s; + stat(fileIt->c_str(), &s); + archive_read_disk_entry_from_file(disk, entry, -1, &s); + // write entry header + archive_write_header(a, entry); + // now copy contents of file into archive a + FILE* file = fopen(fileIt->c_str(), "rb"); + if(!file) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with fopen(): " + << file + << strerror(errno) + << std::endl); + return 0; + } + char buff[cmCPackTGZ_Data_BlockSize]; + int len = fread(buff, 1, sizeof(buff), file); + while (len > 0) + { + archive_write_data(a, buff, len); + len = fread(buff, 1, sizeof(buff), file); + } + // close the file and free the entry + fclose(file); + archive_entry_free(entry); + } + // close the archive and finish the write + archive_write_close(a); + archive_write_finish(a); + return 1; +} + +//---------------------------------------------------------------------- +int cmCPackArchiveGenerator::GenerateHeader(std::ostream*) +{ + return 1; +} diff --git a/Source/CPack/cmCPackArchiveGenerator.h b/Source/CPack/cmCPackArchiveGenerator.h new file mode 100644 index 0000000..486db8e --- /dev/null +++ b/Source/CPack/cmCPackArchiveGenerator.h @@ -0,0 +1,47 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc. + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmCPackArchiveGenerator_h +#define cmCPackArchiveGenerator_h + +#include "cmCPackGenerator.h" + + +/** \class cmCPackArchiveGenerator + * \brief A generator base for libarchive generation + * + */ +class cmCPackArchiveGenerator : public cmCPackGenerator +{ +public: + enum CompressType{ GZIP, BZIP2, COMPRESS, LZMA, NONE}; + enum ArchiveType{ TAR, ZIP}; + cmTypeMacro(cmCPackArchiveGenerator, cmCPackGenerator); + + /** + * Construct generator + */ + cmCPackArchiveGenerator(CompressType, ArchiveType); + virtual ~cmCPackArchiveGenerator(); + // Used to add a header to the archive + virtual int GenerateHeader(std::ostream* os); + +protected: + virtual int InitializeInternal(); + int CompressFiles(const char* outFileName, const char* toplevel, + const std::vector<std::string>& files); + virtual const char* GetOutputExtension() = 0; + CompressType Compress; + ArchiveType Archive; +}; + +#endif diff --git a/Source/CPack/cmCPackTGZGenerator.cxx b/Source/CPack/cmCPackTGZGenerator.cxx index 99574b0..c6ef8ae 100644 --- a/Source/CPack/cmCPackTGZGenerator.cxx +++ b/Source/CPack/cmCPackTGZGenerator.cxx @@ -12,34 +12,11 @@ #include "cmCPackTGZGenerator.h" -#include "cmake.h" -#include "cmGlobalGenerator.h" -#include "cmLocalGenerator.h" -#include "cmSystemTools.h" -#include "cmMakefile.h" -#include "cmGeneratedFileStream.h" -#include "cmCPackLog.h" - -#include <cmsys/SystemTools.hxx> -#include <cm_zlib.h> -#include <libtar/libtar.h> -#include <fcntl.h> -#include <errno.h> - -//---------------------------------------------------------------------- -class cmCPackTGZGeneratorForward -{ - public: - static int GenerateHeader(cmCPackTGZGenerator* gg, std::ostream* os) - { - return gg->GenerateHeader(os); - } -}; - //---------------------------------------------------------------------- cmCPackTGZGenerator::cmCPackTGZGenerator() + :cmCPackArchiveGenerator(cmCPackArchiveGenerator::GZIP, + cmCPackArchiveGenerator::TAR) { - this->Compress = true; } //---------------------------------------------------------------------- @@ -47,248 +24,3 @@ cmCPackTGZGenerator::~cmCPackTGZGenerator() { } -static const size_t cmCPackTGZ_Data_BlockSize = 16384; - -//---------------------------------------------------------------------- -class cmCPackTGZ_Data -{ -public: - cmCPackTGZ_Data(cmCPackTGZGenerator* gen, bool compress) : - OutputStream(0), Generator(gen), - CompressionLevel(Z_DEFAULT_COMPRESSION), - Compress(compress) {} - std::ostream* OutputStream; - cmCPackTGZGenerator* Generator; - char CompressedBuffer[cmCPackTGZ_Data_BlockSize]; - int CompressionLevel; - z_stream ZLibStream; - uLong CRC; - bool Compress; -}; - -//---------------------------------------------------------------------- -extern "C" { - int cmCPackTGZ_Data_Open(void *client_data, const char* name, int oflags, - mode_t mode); - ssize_t cmCPackTGZ_Data_Write(void *client_data, void *buff, size_t n); - int cmCPackTGZ_Data_Close(void *client_data); -} - - -//---------------------------------------------------------------------- -int cmCPackTGZ_Data_Open(void *client_data, const char* pathname, - int, mode_t) -{ - cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data; - - if ( mydata->Compress ) - { - mydata->ZLibStream.zalloc = Z_NULL; - mydata->ZLibStream.zfree = Z_NULL; - mydata->ZLibStream.opaque = Z_NULL; - int strategy = Z_DEFAULT_STRATEGY; - if ( deflateInit2(&mydata->ZLibStream, mydata->CompressionLevel, - Z_DEFLATED, -MAX_WBITS, 8, strategy) != Z_OK ) - { - return -1; - } - } - - cmGeneratedFileStream* gf = new cmGeneratedFileStream; - // Open binary - gf->Open(pathname, false, true); - mydata->OutputStream = gf; - if ( !*mydata->OutputStream ) - { - return -1; - } - - if ( !cmCPackTGZGeneratorForward::GenerateHeader(mydata->Generator,gf)) - { - return -1; - } - - if ( mydata->Compress ) - { - mydata->CRC = crc32(0L, Z_NULL, 0); - } - - return 0; -} - -//---------------------------------------------------------------------- -ssize_t cmCPackTGZ_Data_Write(void *client_data, void *buff, size_t n) -{ - cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data; - - if ( mydata->Compress ) - { - mydata->ZLibStream.avail_in = static_cast<uInt>(n); - mydata->ZLibStream.next_in = reinterpret_cast<Bytef*>(buff); - - do { - mydata->ZLibStream.avail_out = cmCPackTGZ_Data_BlockSize; - mydata->ZLibStream.next_out - = reinterpret_cast<Bytef*>(mydata->CompressedBuffer); - // no bad return value - int ret = deflate(&mydata->ZLibStream, (n?Z_NO_FLUSH:Z_FINISH)); - if(ret == Z_STREAM_ERROR) - { - return 0; - } - - size_t compressedSize - = cmCPackTGZ_Data_BlockSize - mydata->ZLibStream.avail_out; - - mydata->OutputStream->write( - reinterpret_cast<const char*>(mydata->CompressedBuffer), - compressedSize); - } while ( mydata->ZLibStream.avail_out == 0 ); - - if ( !*mydata->OutputStream ) - { - return 0; - } - if ( n ) - { - mydata->CRC = crc32(mydata->CRC, reinterpret_cast<Bytef *>(buff), - static_cast<uInt>(n)); - } - } - else - { - mydata->OutputStream->write(reinterpret_cast<char*>(buff), n); - } - return n; -} - -//---------------------------------------------------------------------- -int cmCPackTGZ_Data_Close(void *client_data) -{ - cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data; - - if ( mydata->Compress ) - { - cmCPackTGZ_Data_Write(client_data, 0, 0); - - char buffer[8]; - int n; - uLong x = mydata->CRC; - for (n = 0; n < 4; n++) { - buffer[n] = static_cast<char>(x & 0xff); - x >>= 8; - } - x = mydata->ZLibStream.total_in; - for (n = 0; n < 4; n++) { - buffer[n+4] = static_cast<char>(x & 0xff); - x >>= 8; - } - - mydata->OutputStream->write(buffer, 8); - (void)deflateEnd(&mydata->ZLibStream); - } - delete mydata->OutputStream; - mydata->OutputStream = 0; - return (0); -} - -//---------------------------------------------------------------------- -int cmCPackTGZGenerator::InitializeInternal() -{ - this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1"); - return this->Superclass::InitializeInternal(); -} - -//---------------------------------------------------------------------- -int cmCPackTGZGenerator::CompressFiles(const char* outFileName, - const char* toplevel, const std::vector<std::string>& files) -{ - cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " - << (toplevel ? toplevel : "(NULL)") << std::endl); - cmCPackTGZ_Data mydata(this, this->Compress); - TAR *t; - char buf[TAR_MAXPATHLEN]; - char pathname[TAR_MAXPATHLEN]; - - tartype_t gztype = { - (openfunc_t)cmCPackTGZ_Data_Open, - (closefunc_t)cmCPackTGZ_Data_Close, - (readfunc_t)0, - (writefunc_t)cmCPackTGZ_Data_Write, - &mydata - }; - - // This libtar is not const safe. Make a non-const copy of outFileName - char* realName = new char[ strlen(outFileName) + 1 ]; - 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, - &gztype, - flags, 0644, - options) == -1) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_open(): " - << strerror(errno) << std::endl); - delete [] realName; - return 0; - } - - delete [] realName; - - 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, 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 cmCPackTGZGenerator::GenerateHeader(std::ostream* os) -{ - if ( this->Compress ) - { - const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ - char header[11]; - 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*/, - 3 /* zlib os code for UNIX, not really used anyway */); - os->write(header, 10); - } - return 1; -} diff --git a/Source/CPack/cmCPackTGZGenerator.h b/Source/CPack/cmCPackTGZGenerator.h index 099775d..3a9fc6b 100644 --- a/Source/CPack/cmCPackTGZGenerator.h +++ b/Source/CPack/cmCPackTGZGenerator.h @@ -13,35 +13,23 @@ #ifndef cmCPackTGZGenerator_h #define cmCPackTGZGenerator_h -#include "cmCPackGenerator.h" - -class cmCPackTGZGeneratorForward; +#include "cmCPackArchiveGenerator.h" /** \class cmCPackTGZGenerator * \brief A generator for TGZ files * - * http://people.freebsd.org/~kientzle/libarchive/ */ -class cmCPackTGZGenerator : public cmCPackGenerator +class cmCPackTGZGenerator : public cmCPackArchiveGenerator { public: - friend class cmCPackTGZGeneratorForward; - cmCPackTypeMacro(cmCPackTGZGenerator, cmCPackGenerator); - + cmCPackTypeMacro(cmCPackTGZGenerator, cmCPackArchiveGenerator); /** * Construct generator */ cmCPackTGZGenerator(); virtual ~cmCPackTGZGenerator(); - protected: - virtual int InitializeInternal(); - virtual int GenerateHeader(std::ostream* os); - int CompressFiles(const char* outFileName, const char* toplevel, - const std::vector<std::string>& files); virtual const char* GetOutputExtension() { return ".tar.gz"; } - - bool Compress; }; #endif diff --git a/Source/CPack/cmCPackTarBZip2Generator.cxx b/Source/CPack/cmCPackTarBZip2Generator.cxx index de7f16c..52826dc 100644 --- a/Source/CPack/cmCPackTarBZip2Generator.cxx +++ b/Source/CPack/cmCPackTarBZip2Generator.cxx @@ -11,29 +11,11 @@ ============================================================================*/ #include "cmCPackTarBZip2Generator.h" - -#include "cmake.h" -#include "cmGlobalGenerator.h" -#include "cmLocalGenerator.h" -#include "cmSystemTools.h" -#include "cmMakefile.h" -#include "cmGeneratedFileStream.h" -#include "cmCPackLog.h" - -#include <cmsys/SystemTools.hxx> - -// Includes needed for implementation of RenameFile. This is not in -// system tools because it is not implemented robustly enough to move -// files across directories. -#ifdef _WIN32 -# include <windows.h> -# include <sys/stat.h> -#endif - //---------------------------------------------------------------------- -cmCPackTarBZip2Generator::cmCPackTarBZip2Generator() +cmCPackTarBZip2Generator::cmCPackTarBZip2Generator() + :cmCPackArchiveGenerator(cmCPackArchiveGenerator::BZIP2, + cmCPackArchiveGenerator::TAR) { - this->Compress = false; } //---------------------------------------------------------------------- @@ -41,135 +23,3 @@ cmCPackTarBZip2Generator::~cmCPackTarBZip2Generator() { } -//---------------------------------------------------------------------- -int cmCPackTarBZip2Generator::InitializeInternal() -{ - this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1"); - std::vector<std::string> path; - std::string pkgPath = cmSystemTools::FindProgram("bzip2", path, false); - if ( pkgPath.empty() ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find BZip2" << std::endl); - return 0; - } - this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str()); - cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Found Compress program: " - << pkgPath.c_str() - << std::endl); - - return this->Superclass::InitializeInternal(); -} - -//---------------------------------------------------------------------- -int cmCPackTarBZip2Generator::BZip2File(const char* packageDirFileName) -{ - int retVal = 0; - cmOStringStream dmgCmd1; - dmgCmd1 << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM") - << "\" \"" << packageDirFileName - << "\""; - retVal = -1; - std::string output; - int res = cmSystemTools::RunSingleCommand(dmgCmd1.str().c_str(), &output, - &retVal, 0, this->GeneratorVerbose, 0); - if ( !res || retVal ) - { - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/CompressBZip2.log"; - cmGeneratedFileStream ofs(tmpFile.c_str()); - ofs << "# Run command: " << dmgCmd1.str().c_str() << std::endl - << "# Output:" << std::endl - << output.c_str() << std::endl; - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running BZip2 command: " - << dmgCmd1.str().c_str() << std::endl - << "Please check " << tmpFile.c_str() << " for errors" << std::endl); - return 0; - } - return 1; -} - -//---------------------------------------------------------------------- -int cmCPackTarBZip2Generator::CompressFiles(const char* outFileName, - const char* toplevel, const std::vector<std::string>& files) -{ - std::string packageDirFileName - = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - packageDirFileName += ".tar"; - std::string output; - if ( !this->Superclass::CompressFiles(packageDirFileName.c_str(), - toplevel, files) ) - { - return 0; - } - - if(!this->BZip2File(packageDirFileName.c_str())) - { - return 0; - } - - std::string compressOutFile = packageDirFileName + ".bz2"; - if ( !cmSystemTools::SameFile(compressOutFile.c_str(), outFileName ) ) - { - if ( !this->RenameFile(compressOutFile.c_str(), outFileName) ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem renaming: \"" - << compressOutFile.c_str() << "\" to \"" - << (outFileName ? outFileName : "(NULL)") << std::endl); - return 0; - } - } - - return 1; -} - -//---------------------------------------------------------------------------- -int cmCPackTarBZip2Generator::RenameFile(const char* oldname, - const char* newname) -{ -#ifdef _WIN32 - /* On Windows the move functions will not replace existing files. - Check if the destination exists. */ - struct stat newFile; - if(stat(newname, &newFile) == 0) - { - /* The destination exists. We have to replace it carefully. The - MoveFileEx function does what we need but is not available on - Win9x. */ - OSVERSIONINFO osv; - DWORD attrs; - - /* Make sure the destination is not read only. */ - attrs = GetFileAttributes(newname); - if(attrs & FILE_ATTRIBUTE_READONLY) - { - SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY); - } - - /* Check the windows version number. */ - osv.dwOSVersionInfoSize = sizeof(osv); - GetVersionEx(&osv); - if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) - { - /* This is Win9x. There is no MoveFileEx implementation. We - cannot quite rename the file atomically. Just delete the - destination and then move the file. */ - DeleteFile(newname); - return MoveFile(oldname, newname); - } - else - { - /* This is not Win9x. Use the MoveFileEx implementation. */ - return MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING); - } - } - else - { - /* The destination does not exist. Just move the file. */ - return MoveFile(oldname, newname); - } -#else - /* On UNIX we have an OS-provided call to do this atomically. */ - return rename(oldname, newname) == 0; -#endif -} - diff --git a/Source/CPack/cmCPackTarBZip2Generator.h b/Source/CPack/cmCPackTarBZip2Generator.h index 7b4ed65..74c244e 100644 --- a/Source/CPack/cmCPackTarBZip2Generator.h +++ b/Source/CPack/cmCPackTarBZip2Generator.h @@ -13,30 +13,22 @@ #ifndef cmCPackTarBZip2Generator_h #define cmCPackTarBZip2Generator_h -#include "cmCPackTGZGenerator.h" +#include "cmCPackArchiveGenerator.h" /** \class cmCPackTarBZip2Generator * \brief A generator for TarBZip2 files */ -class cmCPackTarBZip2Generator : public cmCPackTGZGenerator +class cmCPackTarBZip2Generator : public cmCPackArchiveGenerator { public: - friend class cmCPackTarBZip2GeneratorForward; - cmCPackTypeMacro(cmCPackTarBZip2Generator, cmCPackTGZGenerator); - + cmCPackTypeMacro(cmCPackTarBZip2Generator, cmCPackArchiveGenerator); /** * Construct generator */ cmCPackTarBZip2Generator(); virtual ~cmCPackTarBZip2Generator(); - protected: - virtual int InitializeInternal(); - int CompressFiles(const char* outFileName, const char* toplevel, - const std::vector<std::string>& files); virtual const char* GetOutputExtension() { return ".tar.bz2"; } - int BZip2File(const char* filename); - int RenameFile(const char* oldname, const char* newname); }; #endif diff --git a/Source/CPack/cmCPackTarCompressGenerator.cxx b/Source/CPack/cmCPackTarCompressGenerator.cxx index 165c181..e9b5e2e 100644 --- a/Source/CPack/cmCPackTarCompressGenerator.cxx +++ b/Source/CPack/cmCPackTarCompressGenerator.cxx @@ -12,32 +12,10 @@ #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 <cmsys/SystemTools.hxx> -#include <cmcompress/cmcompress.h> -#include <libtar/libtar.h> -#include <fcntl.h> -#include <errno.h> - //---------------------------------------------------------------------- -class cmCPackTarCompressGeneratorForward -{ -public: - static int GenerateHeader(cmCPackTarCompressGenerator* gg, std::ostream* os) - { - return gg->GenerateHeader(os); - } -}; - -//---------------------------------------------------------------------- -cmCPackTarCompressGenerator::cmCPackTarCompressGenerator() +cmCPackTarCompressGenerator::cmCPackTarCompressGenerator() + :cmCPackArchiveGenerator(cmCPackArchiveGenerator::COMPRESS, + cmCPackArchiveGenerator::TAR) { } @@ -46,206 +24,3 @@ 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<std::string>& 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 - }; - - // This libtar is not const safe. Make a non-const copy of outFileName - char* realName = new char[ strlen(outFileName) + 1 ]; - 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); - delete [] realName; - return 0; - } - - delete [] realName; - - 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, 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<cmcompress_stream*>(client_data); - cmCPackTarCompress_Data *mydata - = static_cast<cmCPackTarCompress_Data*>(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; -} diff --git a/Source/CPack/cmCPackTarCompressGenerator.h b/Source/CPack/cmCPackTarCompressGenerator.h index 3c18056..7ff9a0a 100644 --- a/Source/CPack/cmCPackTarCompressGenerator.h +++ b/Source/CPack/cmCPackTarCompressGenerator.h @@ -18,12 +18,10 @@ /** \class cmCPackTarCompressGenerator * \brief A generator for TarCompress files */ -class cmCPackTarCompressGenerator : public cmCPackTGZGenerator +class cmCPackTarCompressGenerator : public cmCPackArchiveGenerator { public: - friend class cmCPackTarCompressGeneratorForward; - cmCPackTypeMacro(cmCPackTarCompressGenerator, cmCPackTGZGenerator); - + cmCPackTypeMacro(cmCPackTarCompressGenerator, cmCPackArchiveGenerator); /** * Construct generator */ @@ -31,13 +29,7 @@ public: virtual ~cmCPackTarCompressGenerator(); protected: - virtual int InitializeInternal(); - int CompressFiles(const char* outFileName, const char* toplevel, - const std::vector<std::string>& files); virtual const char* GetOutputExtension() { return ".tar.Z"; } - - int RenameFile(const char* oldname, const char* newname); - int GenerateHeader(std::ostream* os); }; #endif diff --git a/Source/CPack/cmCPackZIPGenerator.cxx b/Source/CPack/cmCPackZIPGenerator.cxx index 9924497..e195f83 100644 --- a/Source/CPack/cmCPackZIPGenerator.cxx +++ b/Source/CPack/cmCPackZIPGenerator.cxx @@ -12,14 +12,10 @@ #include "cmCPackZIPGenerator.h" -#include "cmSystemTools.h" -#include "cmGeneratedFileStream.h" -#include "cmCPackLog.h" - -#include <cmsys/SystemTools.hxx> - //---------------------------------------------------------------------- cmCPackZIPGenerator::cmCPackZIPGenerator() + :cmCPackArchiveGenerator(cmCPackArchiveGenerator::NONE, + cmCPackArchiveGenerator::ZIP) { } @@ -28,71 +24,3 @@ cmCPackZIPGenerator::~cmCPackZIPGenerator() { } -//---------------------------------------------------------------------- -int cmCPackZIPGenerator::InitializeInternal() -{ - this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1"); - this->ReadListFile("CPackZIP.cmake"); - if ((!this->IsSet("ZIP_EXECUTABLE")) - || (!this->IsSet("CPACK_ZIP_COMMAND"))) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find a suitable ZIP program" - << std::endl); - return 0; - } - return this->Superclass::InitializeInternal(); -} - -//---------------------------------------------------------------------- -int cmCPackZIPGenerator::CompressFiles(const char* outFileName, - const char* toplevel, const std::vector<std::string>& files) -{ - std::string tempFileName; - tempFileName = toplevel; - tempFileName += "/winZip.filelist"; - bool needQuotesInFile = cmSystemTools::IsOn( - this->GetOption("CPACK_ZIP_NEED_QUOTES")); - - std::string cmd = this->GetOption("CPACK_ZIP_COMMAND"); - cmsys::SystemTools::ReplaceString(cmd, "<ARCHIVE>", outFileName); - cmsys::SystemTools::ReplaceString(cmd, "<FILELIST>", "winZip.filelist"); - - { // the scope is needed for cmGeneratedFileStream - cmGeneratedFileStream out(tempFileName.c_str()); - std::vector<std::string>::const_iterator fileIt; - for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt ) - { - if ( needQuotesInFile ) - { - out << "\""; - } - out << cmSystemTools::RelativePath(toplevel, fileIt->c_str()); - if ( needQuotesInFile ) - { - out << "\""; - } - out << std::endl; - } - } - - - std::string output; - int retVal = -1; - int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, - &retVal, toplevel, this->GeneratorVerbose, 0); - - if ( !res || retVal ) - { - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/CompressZip.log"; - cmGeneratedFileStream ofs(tmpFile.c_str()); - ofs << "# Run command: " << cmd.c_str() << std::endl - << "# Output:" << std::endl - << output.c_str() << std::endl; - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem running zip command: " - << cmd.c_str() << std::endl - << "Please check " << tmpFile.c_str() << " for errors" << std::endl); - return 0; - } - return 1; -} diff --git a/Source/CPack/cmCPackZIPGenerator.h b/Source/CPack/cmCPackZIPGenerator.h index 7ff0dc3..70e1a5f 100644 --- a/Source/CPack/cmCPackZIPGenerator.h +++ b/Source/CPack/cmCPackZIPGenerator.h @@ -13,18 +13,15 @@ #ifndef cmCPackZIPGenerator_h #define cmCPackZIPGenerator_h -#include "cmCPackGenerator.h" - -class cmCPackZIPGeneratorForward; +#include "cmCPackArchiveGenerator.h" /** \class cmCPackZIPGenerator * \brief A generator for ZIP files */ -class cmCPackZIPGenerator : public cmCPackGenerator +class cmCPackZIPGenerator : public cmCPackArchiveGenerator { public: - friend class cmCPackZIPGeneratorForward; - cmCPackTypeMacro(cmCPackZIPGenerator, cmCPackGenerator); + cmCPackTypeMacro(cmCPackZIPGenerator, cmCPackArchiveGenerator); /** * Construct generator @@ -33,12 +30,7 @@ public: virtual ~cmCPackZIPGenerator(); protected: - virtual int InitializeInternal(); - int CompressFiles(const char* outFileName, const char* toplevel, - const std::vector<std::string>& files); virtual const char* GetOutputExtension() { return ".zip"; } - - int ZipStyle; }; #endif diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 031bfc3..d593d7e 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -18,11 +18,13 @@ #ifdef __QNX__ # include <malloc.h> /* for malloc/free on QNX */ #endif - +#include <cmsys/Glob.hxx> #include <cmsys/RegularExpression.hxx> #include <cmsys/Directory.hxx> #include <cmsys/System.h> #if defined(CMAKE_BUILD_WITH_CMAKE) +#include <cmlibarchive/libarchive/archive.h> +#include <cmlibarchive/libarchive/archive_entry.h> # include <cmsys/Terminal.h> #endif #include <cmsys/stl/algorithm> @@ -45,9 +47,8 @@ #endif #if defined(CMAKE_BUILD_WITH_CMAKE) -# include <libtar/libtar.h> +# include <memory> // auto_ptr # include <fcntl.h> -# include <cm_zlib.h> # include <cmsys/MD5.h> #endif @@ -1701,166 +1702,111 @@ bool cmSystemTools::IsPathToFramework(const char* path) return false; } -#if defined(CMAKE_BUILD_WITH_CMAKE) -struct cmSystemToolsGZStruct -{ - gzFile GZFile; -}; - -extern "C" { - int cmSystemToolsGZStructOpen(void* call_data, const char *pathname, - int oflags, mode_t mode); - int cmSystemToolsGZStructClose(void* call_data); - ssize_t cmSystemToolsGZStructRead(void* call_data, void* buf, size_t count); - ssize_t cmSystemToolsGZStructWrite(void* call_data, const void* buf, - size_t count); -} - -int cmSystemToolsGZStructOpen(void* call_data, const char *pathname, - int oflags, mode_t mode) -{ - const char *gzoflags; - int fd; - - cmSystemToolsGZStruct* gzf = static_cast<cmSystemToolsGZStruct*>(call_data); - - switch (oflags & O_ACCMODE) - { - case O_WRONLY: - gzoflags = "wb"; - break; - case O_RDONLY: - gzoflags = "rb"; - break; - default: - case O_RDWR: - errno = EINVAL; - return -1; - } - - fd = open(pathname, oflags, mode); - if (fd == -1) - { - return -1; - } - -// no fchmod on BeOS 5...do pathname instead. -#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__) - if ((oflags & O_CREAT) && chmod(pathname, mode)) - { - return -1; - } -#elif !defined(_WIN32) || defined(__CYGWIN__) - if ((oflags & O_CREAT) && fchmod(fd, mode)) - { - return -1; - } -#endif - - gzf->GZFile = gzdopen(fd, gzoflags); - if (!gzf->GZFile) - { - errno = ENOMEM; - return -1; - } - - return fd; -} - -int cmSystemToolsGZStructClose(void* call_data) -{ - cmSystemToolsGZStruct* gzf = static_cast<cmSystemToolsGZStruct*>(call_data); - return gzclose(gzf->GZFile); -} - -ssize_t cmSystemToolsGZStructRead(void* call_data, void* buf, size_t count) -{ - cmSystemToolsGZStruct* gzf = static_cast<cmSystemToolsGZStruct*>(call_data); - return gzread(gzf->GZFile, buf, static_cast<int>(count)); -} - -ssize_t cmSystemToolsGZStructWrite(void* call_data, const void* buf, - size_t count) -{ - cmSystemToolsGZStruct* gzf = static_cast<cmSystemToolsGZStruct*>(call_data); - return gzwrite(gzf->GZFile, (void*)buf, static_cast<int>(count)); -} - -#endif - bool cmSystemTools::CreateTar(const char* outFileName, const std::vector<cmStdString>& files, bool gzip, bool verbose) { -#if defined(CMAKE_BUILD_WITH_CMAKE) - TAR *t; - char buf[TAR_MAXPATHLEN]; - char pathname[TAR_MAXPATHLEN]; - cmSystemToolsGZStruct gzs; - - tartype_t gztype = { - (openfunc_t)cmSystemToolsGZStructOpen, - (closefunc_t)cmSystemToolsGZStructClose, - (readfunc_t)cmSystemToolsGZStructRead, - (writefunc_t)cmSystemToolsGZStructWrite, - &gzs - }; - - // This libtar is not const safe. Make a non-const copy of outFileName - char* realName = new char[ strlen(outFileName) + 1 ]; - strcpy(realName, outFileName); - int options = 0; - if(verbose) +#if defined(CMAKE_BUILD_WITH_CMAKE) + std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); + // recursively expand all directories in files so that we have a list + // of files + std::vector<std::string> expandedFiles; + for(std::vector<cmStdString>::const_iterator i = files.begin(); + i != files.end(); ++i) { - options |= TAR_VERBOSE; - } -#ifdef __CYGWIN__ - options |= TAR_GNU; -#endif - if (tar_open(&t, realName, - (gzip? &gztype : NULL), - O_WRONLY | O_CREAT, 0644, - options) == -1) - { - cmSystemTools::Error("Problem with tar_open(): ", strerror(errno)); - delete [] realName; - return false; + if(cmSystemTools::FileIsDirectory(i->c_str())) + { + cmsys::Glob gl; + std::string findExpr = *i; + if ( findExpr[findExpr.size()-1] != '/' ) + { + findExpr +="/"; + } + findExpr += "*"; + gl.RecurseOn(); + if ( gl.FindFiles(findExpr) ) + { + std::vector<std::string> dirfiles = gl.GetFiles(); + std::copy(dirfiles.begin(), dirfiles.end(), + std::back_inserter(expandedFiles)); + } + } + else + { + if(!cmSystemTools::FileIsFullPath(i->c_str())) + { + std::string fullp = cwd + "/" + *i; + expandedFiles.push_back(fullp); + } + else + { + expandedFiles.push_back(*i); + } + } } - - delete [] realName; - - std::vector<cmStdString>::const_iterator it; - for (it = files.begin(); it != files.end(); ++ it ) + int res; + // create a new archive + struct archive* a = archive_write_new(); + if(gzip) { - strncpy(pathname, it->c_str(), sizeof(pathname)); - pathname[sizeof(pathname)-1] = 0; - strncpy(buf, pathname, sizeof(buf)); - buf[sizeof(buf)-1] = 0; - if (tar_append_tree(t, buf, pathname) != 0) + res = archive_write_set_compression_gzip(a); + if(res != ARCHIVE_OK) { - cmOStringStream ostr; - ostr << "Problem with tar_append_tree(\"" << buf << "\", \"" - << pathname << "\"): " - << strerror(errno); - cmSystemTools::Error(ostr.str().c_str()); - tar_close(t); - return false; + cmSystemTools::Error("Unable to use gzip in libarchive"); } - } - - if (tar_append_eof(t) != 0) + } + res = archive_write_set_format_ustar(a); + if(res != ARCHIVE_OK) { - cmSystemTools::Error("Problem with tar_append_eof(): ", strerror(errno)); - tar_close(t); - return false; + cmSystemTools::Error("Unable to use tar libarchive"); } - - if (tar_close(t) != 0) + archive_write_open_file(a, outFileName); + // create a new disk struct + struct archive* disk = archive_read_disk_new(); + archive_read_disk_set_standard_lookup(disk); + std::vector<std::string>::const_iterator fileIt; + for ( fileIt = expandedFiles.begin(); + fileIt != expandedFiles.end(); ++ fileIt ) { - cmSystemTools::Error("Problem with tar_close(): ", strerror(errno)); - return false; + // create a new entry for each file + struct archive_entry *entry = archive_entry_new(); + // Get the relative path to the file + std::string rp = cmSystemTools::RelativePath(cwd.c_str(), + fileIt->c_str()); + if(verbose) + { + std::cout << rp << "\n"; + } + // Set the name of the entry to the file name + archive_entry_set_pathname(entry, rp.c_str()); + // get the information about the file from stat + struct stat s; + stat(fileIt->c_str(), &s); + archive_read_disk_entry_from_file(disk, entry, -1, &s); + // write entry header + archive_write_header(a, entry); + // now copy contents of file into archive a + FILE* file = fopen(fileIt->c_str(), "rb"); + if(!file) + { + cmSystemTools::Error("Problem with fopen(): ", + fileIt->c_str()); + return false; + } + char buff[16384]; + int len = fread(buff, 1, sizeof(buff), file); + while (len > 0) + { + archive_write_data(a, buff, len); + len = fread(buff, 1, sizeof(buff), file); + } + // close the file and free the entry + fclose(file); + archive_entry_free(entry); } - + // close the archive and finish the write + archive_write_close(a); + archive_write_finish(a); return true; #else (void)outFileName; @@ -1871,130 +1817,245 @@ bool cmSystemTools::CreateTar(const char* outFileName, #endif } -bool cmSystemTools::ExtractTar(const char* outFileName, - const std::vector<cmStdString>& files, - bool gzip, bool verbose) -{ - (void)files; #if defined(CMAKE_BUILD_WITH_CMAKE) - TAR *t; - cmSystemToolsGZStruct gzs; - - tartype_t gztype = { - cmSystemToolsGZStructOpen, - cmSystemToolsGZStructClose, - cmSystemToolsGZStructRead, - cmSystemToolsGZStructWrite, - &gzs - }; - - // This libtar is not const safe. Make a non-const copy of outFileName - char* realName = new char[ strlen(outFileName) + 1 ]; - strcpy(realName, outFileName); - if (tar_open(&t, realName, - (gzip? &gztype : NULL), - O_RDONLY -#ifdef _WIN32 - | O_BINARY -#endif - , 0, - (verbose?TAR_VERBOSE:0) - | 0) == -1) +namespace{ +#define BSDTAR_FILESIZE_PRINTF "%lu" +#define BSDTAR_FILESIZE_TYPE unsigned long + void +list_item_verbose(FILE *out, struct archive_entry *entry) +{ + char tmp[100]; + size_t w; + const char *p; + const char *fmt; + time_t tim; + static time_t now; + size_t u_width = 6; + size_t gs_width = 13; + + /* + * We avoid collecting the entire list in memory at once by + * listing things as we see them. However, that also means we can't + * just pre-compute the field widths. Instead, we start with guesses + * and just widen them as necessary. These numbers are completely + * arbitrary. + */ + if (!now) + { + time(&now); + } + fprintf(out, "%s %d ", + archive_entry_strmode(entry), + archive_entry_nlink(entry)); + + /* Use uname if it's present, else uid. */ + p = archive_entry_uname(entry); + if ((p == NULL) || (*p == '\0')) { - cmSystemTools::Error("Problem with tar_open(): ", strerror(errno)); - delete [] realName; - return false; + sprintf(tmp, "%lu ", + (unsigned long)archive_entry_uid(entry)); + p = tmp; } - - delete [] realName; - - if (tar_extract_all(t, 0) != 0) - { - cmSystemTools::Error("Problem with tar_extract_all(): ", strerror(errno)); - return false; - } - - if (tar_close(t) != 0) + w = strlen(p); + if (w > u_width) { - cmSystemTools::Error("Problem with tar_close(): ", strerror(errno)); - return false; + u_width = w; } - return true; + fprintf(out, "%-*s ", (int)u_width, p); + + /* Use gname if it's present, else gid. */ + p = archive_entry_gname(entry); + if (p != NULL && p[0] != '\0') + { + fprintf(out, "%s", p); + w = strlen(p); + } + else + { + sprintf(tmp, "%lu", + (unsigned long)archive_entry_gid(entry)); + w = strlen(tmp); + fprintf(out, "%s", tmp); + } + + /* + * Print device number or file size, right-aligned so as to make + * total width of group and devnum/filesize fields be gs_width. + * If gs_width is too small, grow it. + */ + if (archive_entry_filetype(entry) == AE_IFCHR + || archive_entry_filetype(entry) == AE_IFBLK) + { + sprintf(tmp, "%lu,%lu", + (unsigned long)archive_entry_rdevmajor(entry), + (unsigned long)archive_entry_rdevminor(entry)); + } + else + { + /* + * Note the use of platform-dependent macros to format + * the filesize here. We need the format string and the + * corresponding type for the cast. + */ + sprintf(tmp, BSDTAR_FILESIZE_PRINTF, + (BSDTAR_FILESIZE_TYPE)archive_entry_size(entry)); + } + if (w + strlen(tmp) >= gs_width) + { + gs_width = w+strlen(tmp)+1; + } + fprintf(out, "%*s", (int)(gs_width - w), tmp); + + /* Format the time using 'ls -l' conventions. */ + tim = archive_entry_mtime(entry); +#define HALF_YEAR (time_t)365 * 86400 / 2 +#if defined(_WIN32) && !defined(__CYGWIN__) +#define DAY_FMT "%d" /* Windows' strftime function does not support %e format. */ #else - (void)outFileName; - (void)gzip; - (void)verbose; - return false; +#define DAY_FMT "%e" /* Day number without leading zeros */ #endif + if (tim < now - HALF_YEAR || tim > now + HALF_YEAR) + { + fmt = DAY_FMT " %b %Y"; + } + else + { + fmt = DAY_FMT " %b %H:%M"; + } + strftime(tmp, sizeof(tmp), fmt, localtime(&tim)); + fprintf(out, " %s ", tmp); + fprintf(out, "%s", archive_entry_pathname(entry)); + + /* Extra information for links. */ + if (archive_entry_hardlink(entry)) /* Hard link */ + { + fprintf(out, " link to %s", + archive_entry_hardlink(entry)); + } + else if (archive_entry_symlink(entry)) /* Symbolic link */ + { + fprintf(out, " -> %s", archive_entry_symlink(entry)); + } } - -bool cmSystemTools::ListTar(const char* outFileName, - std::vector<cmStdString>& files, bool gzip, - bool verbose) + +int copy_data(struct archive *ar, struct archive *aw) { -#if defined(CMAKE_BUILD_WITH_CMAKE) - TAR *t; - cmSystemToolsGZStruct gzs; - - tartype_t gztype = { - cmSystemToolsGZStructOpen, - cmSystemToolsGZStructClose, - cmSystemToolsGZStructRead, - cmSystemToolsGZStructWrite, - &gzs - }; - - // This libtar is not const safe. Make a non-const copy of outFileName - char* realName = new char[ strlen(outFileName) + 1 ]; - strcpy(realName, outFileName); - if (tar_open(&t, realName, - (gzip? &gztype : NULL), - O_RDONLY -#ifdef _WIN32 - | O_BINARY -#endif - , 0, - (verbose?TAR_VERBOSE:0) - | 0) == -1) + int r; + const void *buff; + size_t size; + off_t offset; + + for (;;) { - cmSystemTools::Error("Problem with tar_open(): ", strerror(errno)); - delete [] realName; - return false; + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + { + return (ARCHIVE_OK); + } + if (r != ARCHIVE_OK) + { + return (r); + } + r = archive_write_data_block(aw, buff, size, offset); + if (r != ARCHIVE_OK) + { + cmSystemTools::Message("archive_write_data_block()", + archive_error_string(aw)); + return (r); + } } +} - delete [] realName; - - while ((th_read(t)) == 0) - { - const char* filename = th_get_pathname(t); - files.push_back(filename); - - if ( verbose ) +bool extract_tar(const char* outFileName, bool verbose, bool extract) +{ + struct archive* a = archive_read_new(); + struct archive *ext = archive_write_disk_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + struct archive_entry *entry; + int r = archive_read_open_file(a, outFileName, 10240); + if(r) + { + cmSystemTools::Error("Problem with archive_read_open_file(): ", + archive_error_string(a)); + return false; + } + for (;;) + { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + { + break; + } + if (r != ARCHIVE_OK) + { + cmSystemTools::Error("Problem with archive_read_next_header(): ", + archive_error_string(a)); + } + if (verbose && extract) + { + cmSystemTools::Stdout("x "); + } + if(verbose && !extract) { - th_print_long_ls(t); + list_item_verbose(stdout, entry); } else { - std::cout << filename << std::endl; + cmSystemTools::Stdout(archive_entry_pathname(entry)); } - -#ifdef DEBUG - th_print(t); -#endif - if (TH_ISREG(t) && tar_skip_regfile(t) != 0) + if(extract) { - cmSystemTools::Error("Problem with tar_skip_regfile(): ", - strerror(errno)); - return false; + r = archive_write_header(ext, entry); + if (r != ARCHIVE_OK) + { + cmSystemTools::Error("Problem with archive_write_header(): ", + archive_error_string(a)); + } + else + { + copy_data(a, ext); + r = archive_write_finish_entry(ext); + if (r != ARCHIVE_OK) + { + cmSystemTools::Error("Problem with archive_write_finish_entry(): ", + archive_error_string(ext)); + } + } + } + if (verbose || !extract) + { + cmSystemTools::Stdout("\n"); } - } - - if (tar_close(t) != 0) - { - cmSystemTools::Error("Problem with tar_close(): ", strerror(errno)); - return false; } + archive_read_close(a); + archive_read_finish(a); return true; + +} +} +#endif + +bool cmSystemTools::ExtractTar(const char* outFileName, + const std::vector<cmStdString>& files, + bool , bool verbose) +{ + (void)files; +#if defined(CMAKE_BUILD_WITH_CMAKE) + return extract_tar(outFileName, verbose, true); +#else + (void)outFileName; + (void)verbose; + return false; +#endif +} + +bool cmSystemTools::ListTar(const char* outFileName, + std::vector<cmStdString>& files, bool gzip, + bool verbose) +{ +#if defined(CMAKE_BUILD_WITH_CMAKE) + return extract_tar(outFileName, verbose, false); #else (void)outFileName; (void)files; |