summaryrefslogtreecommitdiffstats
path: root/Source/CPack/cmCPackArchiveGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CPack/cmCPackArchiveGenerator.cxx')
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx230
1 files changed, 230 insertions, 0 deletions
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;
+}