1//===- FileUpdate.cpp - Conditionally update a file -----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// FileUpdate is a utility for conditionally updating a file from its input 11// based on whether the input differs from the output. It is used to avoid 12// unnecessary modifications in a build system. 13// 14//===----------------------------------------------------------------------===// 15 16#include "llvm/Support/CommandLine.h" 17#include "llvm/Support/MemoryBuffer.h" 18#include "llvm/ADT/OwningPtr.h" 19#include "llvm/Support/PrettyStackTrace.h" 20#include "llvm/Support/ToolOutputFile.h" 21#include "llvm/Support/Signals.h" 22#include "llvm/Support/system_error.h" 23using namespace llvm; 24 25static cl::opt<bool> 26Quiet("quiet", cl::desc("Don't print unnecessary status information"), 27 cl::init(false)); 28 29static cl::opt<std::string> 30InputFilename("input-file", cl::desc("Input file (defaults to stdin)"), 31 cl::init("-"), cl::value_desc("filename")); 32 33static cl::opt<std::string> 34OutputFilename(cl::Positional, cl::desc("<output-file>"), cl::Required); 35 36int main(int argc, char **argv) { 37 sys::PrintStackTraceOnErrorSignal(); 38 PrettyStackTraceProgram X(argc, argv); 39 cl::ParseCommandLineOptions(argc, argv); 40 41 if (OutputFilename == "-") { 42 errs() << argv[0] << ": error: Can't update standard output\n"; 43 return 1; 44 } 45 46 // Get the input data. 47 OwningPtr<MemoryBuffer> In; 48 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), In)) { 49 errs() << argv[0] << ": error: Unable to get input '" 50 << InputFilename << "': " << ec.message() << '\n'; 51 return 1; 52 } 53 54 // Get the output data. 55 OwningPtr<MemoryBuffer> Out; 56 MemoryBuffer::getFile(OutputFilename.c_str(), Out); 57 58 // If the output exists and the contents match, we are done. 59 if (Out && In->getBufferSize() == Out->getBufferSize() && 60 memcmp(In->getBufferStart(), Out->getBufferStart(), 61 Out->getBufferSize()) == 0) { 62 if (!Quiet) 63 errs() << argv[0] << ": Not updating '" << OutputFilename 64 << "', contents match input.\n"; 65 return 0; 66 } 67 68 // Otherwise, overwrite the output. 69 if (!Quiet) 70 errs() << argv[0] << ": Updating '" << OutputFilename 71 << "', contents changed.\n"; 72 std::string ErrorStr; 73 tool_output_file OutStream(OutputFilename.c_str(), ErrorStr, 74 raw_fd_ostream::F_Binary); 75 if (!ErrorStr.empty()) { 76 errs() << argv[0] << ": Unable to write output '" 77 << OutputFilename << "': " << ErrorStr << '\n'; 78 return 1; 79 } 80 81 OutStream.os().write(In->getBufferStart(), In->getBufferSize()); 82 83 // Declare success. 84 OutStream.keep(); 85 86 return 0; 87} 88