Initial commit.
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / CPack / cmCPackTGZGenerator.cxx
blob51c71a66f003b3fc1759e879d5b50c8706d6b1ab
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCPackTGZGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2007/09/27 18:44:10 $
7 Version: $Revision: 1.19 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
18 #include "cmCPackTGZGenerator.h"
20 #include "cmake.h"
21 #include "cmGlobalGenerator.h"
22 #include "cmLocalGenerator.h"
23 #include "cmSystemTools.h"
24 #include "cmMakefile.h"
25 #include "cmGeneratedFileStream.h"
26 #include "cmCPackLog.h"
28 #include <cmsys/SystemTools.hxx>
29 #include <cm_zlib.h>
30 #include <libtar/libtar.h>
31 #include <memory> // auto_ptr
32 #include <fcntl.h>
33 #include <errno.h>
35 //----------------------------------------------------------------------
36 class cmCPackTGZGeneratorForward
38 public:
39 static int GenerateHeader(cmCPackTGZGenerator* gg, std::ostream* os)
41 return gg->GenerateHeader(os);
45 //----------------------------------------------------------------------
46 cmCPackTGZGenerator::cmCPackTGZGenerator()
48 this->Compress = true;
51 //----------------------------------------------------------------------
52 cmCPackTGZGenerator::~cmCPackTGZGenerator()
56 static const size_t cmCPackTGZ_Data_BlockSize = 16384;
58 //----------------------------------------------------------------------
59 class cmCPackTGZ_Data
61 public:
62 cmCPackTGZ_Data(cmCPackTGZGenerator* gen, bool compress) :
63 OutputStream(0), Generator(gen),
64 CompressionLevel(Z_DEFAULT_COMPRESSION),
65 Compress(compress) {}
66 std::ostream* OutputStream;
67 cmCPackTGZGenerator* Generator;
68 char CompressedBuffer[cmCPackTGZ_Data_BlockSize];
69 int CompressionLevel;
70 z_stream ZLibStream;
71 uLong CRC;
72 bool Compress;
75 //----------------------------------------------------------------------
76 extern "C" {
77 int cmCPackTGZ_Data_Open(void *client_data, const char* name, int oflags,
78 mode_t mode);
79 ssize_t cmCPackTGZ_Data_Write(void *client_data, void *buff, size_t n);
80 int cmCPackTGZ_Data_Close(void *client_data);
84 //----------------------------------------------------------------------
85 int cmCPackTGZ_Data_Open(void *client_data, const char* pathname,
86 int, mode_t)
88 cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data;
90 if ( mydata->Compress )
92 mydata->ZLibStream.zalloc = Z_NULL;
93 mydata->ZLibStream.zfree = Z_NULL;
94 mydata->ZLibStream.opaque = Z_NULL;
95 int strategy = Z_DEFAULT_STRATEGY;
96 if ( deflateInit2(&mydata->ZLibStream, mydata->CompressionLevel,
97 Z_DEFLATED, -MAX_WBITS, 8, strategy) != Z_OK )
99 return -1;
103 cmGeneratedFileStream* gf = new cmGeneratedFileStream;
104 // Open binary
105 gf->Open(pathname, false, true);
106 mydata->OutputStream = gf;
107 if ( !*mydata->OutputStream )
109 return -1;
112 if ( !cmCPackTGZGeneratorForward::GenerateHeader(mydata->Generator,gf))
114 return -1;
117 if ( mydata->Compress )
119 mydata->CRC = crc32(0L, Z_NULL, 0);
122 return 0;
125 //----------------------------------------------------------------------
126 ssize_t cmCPackTGZ_Data_Write(void *client_data, void *buff, size_t n)
128 cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data;
130 if ( mydata->Compress )
132 mydata->ZLibStream.avail_in = static_cast<uInt>(n);
133 mydata->ZLibStream.next_in = reinterpret_cast<Bytef*>(buff);
135 do {
136 mydata->ZLibStream.avail_out = cmCPackTGZ_Data_BlockSize;
137 mydata->ZLibStream.next_out
138 = reinterpret_cast<Bytef*>(mydata->CompressedBuffer);
139 // no bad return value
140 int ret = deflate(&mydata->ZLibStream, (n?Z_NO_FLUSH:Z_FINISH));
141 if(ret == Z_STREAM_ERROR)
143 return 0;
146 size_t compressedSize
147 = cmCPackTGZ_Data_BlockSize - mydata->ZLibStream.avail_out;
149 mydata->OutputStream->write(
150 reinterpret_cast<const char*>(mydata->CompressedBuffer),
151 compressedSize);
152 } while ( mydata->ZLibStream.avail_out == 0 );
154 if ( !*mydata->OutputStream )
156 return 0;
158 if ( n )
160 mydata->CRC = crc32(mydata->CRC, reinterpret_cast<Bytef *>(buff),
161 static_cast<uInt>(n));
164 else
166 mydata->OutputStream->write(reinterpret_cast<char*>(buff), n);
168 return n;
171 //----------------------------------------------------------------------
172 int cmCPackTGZ_Data_Close(void *client_data)
174 cmCPackTGZ_Data *mydata = (cmCPackTGZ_Data*)client_data;
176 if ( mydata->Compress )
178 cmCPackTGZ_Data_Write(client_data, 0, 0);
180 char buffer[8];
181 int n;
182 uLong x = mydata->CRC;
183 for (n = 0; n < 4; n++) {
184 buffer[n] = (int)(x & 0xff);
185 x >>= 8;
187 x = mydata->ZLibStream.total_in;
188 for (n = 0; n < 4; n++) {
189 buffer[n+4] = (int)(x & 0xff);
190 x >>= 8;
193 mydata->OutputStream->write(buffer, 8);
194 (void)deflateEnd(&mydata->ZLibStream);
196 delete mydata->OutputStream;
197 mydata->OutputStream = 0;
198 return (0);
201 //----------------------------------------------------------------------
202 int cmCPackTGZGenerator::InitializeInternal()
204 this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
205 return this->Superclass::InitializeInternal();
208 //----------------------------------------------------------------------
209 int cmCPackTGZGenerator::CompressFiles(const char* outFileName,
210 const char* toplevel, const std::vector<std::string>& files)
212 cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
213 << (toplevel ? toplevel : "(NULL)") << std::endl);
214 cmCPackTGZ_Data mydata(this, this->Compress);
215 TAR *t;
216 char buf[TAR_MAXPATHLEN];
217 char pathname[TAR_MAXPATHLEN];
219 tartype_t gztype = {
220 (openfunc_t)cmCPackTGZ_Data_Open,
221 (closefunc_t)cmCPackTGZ_Data_Close,
222 (readfunc_t)0,
223 (writefunc_t)cmCPackTGZ_Data_Write,
224 &mydata
227 // Ok, this libtar is not const safe. for now use auto_ptr hack
228 char* realName = new char[ strlen(outFileName) + 1 ];
229 std::auto_ptr<char> realNamePtr(realName);
230 strcpy(realName, outFileName);
231 int flags = O_WRONLY | O_CREAT;
232 int options = 0;
233 if(this->GeneratorVerbose)
235 options |= TAR_VERBOSE;
237 #ifdef __CYGWIN__
238 options |= TAR_GNU;
239 #endif
240 if (tar_open(&t, realName,
241 &gztype,
242 flags, 0644,
243 options) == -1)
245 cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_open(): "
246 << strerror(errno) << std::endl);
247 return 0;
250 std::vector<std::string>::const_iterator fileIt;
251 for ( fileIt = files.begin(); fileIt != files.end(); ++ fileIt )
253 std::string rp = cmSystemTools::RelativePath(toplevel, fileIt->c_str());
254 strncpy(pathname, fileIt->c_str(), sizeof(pathname));
255 pathname[sizeof(pathname)-1] = 0;
256 strncpy(buf, rp.c_str(), sizeof(buf));
257 buf[sizeof(buf)-1] = 0;
258 if (tar_append_tree(t, pathname, buf) != 0)
260 cmCPackLogger(cmCPackLog::LOG_ERROR,
261 "Problem with tar_append_tree(\"" << buf << "\", \""
262 << pathname << "\"): "
263 << strerror(errno) << std::endl);
264 tar_close(t);
265 return 0;
268 if (tar_append_eof(t) != 0)
270 cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_append_eof(): "
271 << strerror(errno) << std::endl);
272 tar_close(t);
273 return 0;
276 if (tar_close(t) != 0)
278 cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem with tar_close(): "
279 << strerror(errno) << std::endl);
280 return 0;
282 return 1;
285 //----------------------------------------------------------------------
286 int cmCPackTGZGenerator::GenerateHeader(std::ostream* os)
288 if ( this->Compress )
290 const int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
291 char header[11];
292 sprintf(header, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
293 Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/,
294 3 /* zlib os code for UNIX, not really used anyway */);
295 os->write(header, 10);
297 return 1;