1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #include "cmGeneratedFileStream.h"
14 #include "cmSystemTools.h"
16 #if defined(CMAKE_BUILD_WITH_CMAKE)
20 //----------------------------------------------------------------------------
21 cmGeneratedFileStream::cmGeneratedFileStream():
22 cmGeneratedFileStreamBase(), Stream()
26 //----------------------------------------------------------------------------
27 cmGeneratedFileStream::cmGeneratedFileStream(const char* name, bool quiet):
28 cmGeneratedFileStreamBase(name),
29 Stream(TempName.c_str())
31 // Check if the file opened.
34 cmSystemTools::Error("Cannot open file for write: ",
35 this->TempName.c_str());
36 cmSystemTools::ReportLastSystemError("");
40 //----------------------------------------------------------------------------
41 cmGeneratedFileStream::~cmGeneratedFileStream()
43 // This is the first destructor called. Check the status of the
44 // stream and give the information to the private base. Next the
45 // stream will be destroyed which will close the temporary file.
46 // Finally the base destructor will be called to replace the
48 this->Okay = (*this)?true:false;
51 //----------------------------------------------------------------------------
52 cmGeneratedFileStream&
53 cmGeneratedFileStream::Open(const char* name, bool quiet, bool binaryFlag)
55 // Store the file name and construct the temporary file name.
56 this->cmGeneratedFileStreamBase::Open(name);
58 // Open the temporary output file.
61 this->Stream::open(this->TempName.c_str(),
62 std::ios::out | std::ios::binary);
66 this->Stream::open(this->TempName.c_str(), std::ios::out);
69 // Check if the file opened.
72 cmSystemTools::Error("Cannot open file for write: ",
73 this->TempName.c_str());
74 cmSystemTools::ReportLastSystemError("");
79 //----------------------------------------------------------------------------
81 cmGeneratedFileStream::Close()
83 // Save whether the temporary output file is valid before closing.
84 this->Okay = (*this)?true:false;
86 // Close the temporary output file.
87 this->Stream::close();
89 // Remove the temporary file (possibly by renaming to the real file).
90 return this->cmGeneratedFileStreamBase::Close();
93 //----------------------------------------------------------------------------
94 void cmGeneratedFileStream::SetCopyIfDifferent(bool copy_if_different)
96 this->CopyIfDifferent = copy_if_different;
99 //----------------------------------------------------------------------------
100 void cmGeneratedFileStream::SetCompression(bool compression)
102 this->Compress = compression;
105 //----------------------------------------------------------------------------
106 void cmGeneratedFileStream::SetCompressionExtraExtension(bool ext)
108 this->CompressExtraExtension = ext;
111 //----------------------------------------------------------------------------
112 cmGeneratedFileStreamBase::cmGeneratedFileStreamBase():
115 CopyIfDifferent(false),
118 CompressExtraExtension(true)
122 //----------------------------------------------------------------------------
123 cmGeneratedFileStreamBase::cmGeneratedFileStreamBase(const char* name):
126 CopyIfDifferent(false),
129 CompressExtraExtension(true)
134 //----------------------------------------------------------------------------
135 cmGeneratedFileStreamBase::~cmGeneratedFileStreamBase()
140 //----------------------------------------------------------------------------
141 void cmGeneratedFileStreamBase::Open(const char* name)
143 // Save the original name of the file.
146 // Create the name of the temporary file.
147 this->TempName = name;
149 this->TempName += "_tmp";
151 this->TempName += ".tmp";
154 // Make sure the temporary file that will be used is not present.
155 cmSystemTools::RemoveFile(this->TempName.c_str());
157 std::string dir = cmSystemTools::GetFilenamePath(this->TempName);
158 cmSystemTools::MakeDirectory(dir.c_str());
161 //----------------------------------------------------------------------------
162 bool cmGeneratedFileStreamBase::Close()
164 bool replaced = false;
166 std::string resname = this->Name;
167 if ( this->Compress && this->CompressExtraExtension )
172 // Only consider replacing the destination file if no error
174 if(!this->Name.empty() &&
176 (!this->CopyIfDifferent ||
177 cmSystemTools::FilesDiffer(this->TempName.c_str(), resname.c_str())))
179 // The destination is to be replaced. Rename the temporary to the
180 // destination atomically.
181 if ( this->Compress )
183 std::string gzname = this->TempName + ".temp.gz";
184 if ( this->CompressFile(this->TempName.c_str(), gzname.c_str()) )
186 this->RenameFile(gzname.c_str(), resname.c_str());
188 cmSystemTools::RemoveFile(gzname.c_str());
192 this->RenameFile(this->TempName.c_str(), resname.c_str());
198 // Else, the destination was not replaced.
200 // Always delete the temporary file. We never want it to stay around.
201 cmSystemTools::RemoveFile(this->TempName.c_str());
206 //----------------------------------------------------------------------------
207 #ifdef CMAKE_BUILD_WITH_CMAKE
208 int cmGeneratedFileStreamBase::CompressFile(const char* oldname,
211 gzFile gf = gzopen(newname, "w");
216 FILE* ifs = fopen(oldname, "r");
222 const size_t BUFFER_SIZE = 1024;
223 char buffer[BUFFER_SIZE];
224 while ( (res = fread(buffer, 1, BUFFER_SIZE, ifs)) > 0 )
226 if ( !gzwrite(gf, buffer, static_cast<int>(res)) )
238 int cmGeneratedFileStreamBase::CompressFile(const char*, const char*)
244 //----------------------------------------------------------------------------
245 int cmGeneratedFileStreamBase::RenameFile(const char* oldname,
248 return cmSystemTools::RenameFile(oldname, newname);
251 //----------------------------------------------------------------------------
252 void cmGeneratedFileStream::SetName(const char* fname)