1//===- ToolOutputFile.cpp -------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include <mcld/Support/ToolOutputFile.h>
10
11#include <mcld/Support/Path.h>
12#include <mcld/Support/FileHandle.h>
13#include <mcld/Support/MemoryArea.h>
14
15#include <mcld/Support/SystemUtils.h>
16#include <mcld/Support/MsgHandling.h>
17
18#include <llvm/Support/FileUtilities.h>
19#include <llvm/Support/Signals.h>
20#include <llvm/Support/Path.h>
21#include <llvm/Support/FormattedStream.h>
22
23using namespace mcld;
24
25//===----------------------------------------------------------------------===//
26// CleanupInstaller
27//===----------------------------------------------------------------------===//
28ToolOutputFile::CleanupInstaller::CleanupInstaller(const sys::fs::Path& pPath)
29  : Keep(false), m_Path(pPath) {
30  // Arrange for the file to be deleted if the process is killed.
31  if ("-" != m_Path.native())
32    llvm::sys::RemoveFileOnSignal(m_Path.native());
33}
34
35ToolOutputFile::CleanupInstaller::~CleanupInstaller()
36{
37  // Delete the file if the client hasn't told us not to.
38  // FIXME: In Windows, some path in CJK characters can not be removed by LLVM
39  // llvm::sys::Path
40  if (!Keep && "_" != m_Path.native()) {
41    bool Existed = false;
42    llvm::sys::fs::remove(m_Path.native(), Existed);
43  }
44
45  // Ok, the file is successfully written and closed, or deleted. There's no
46  // further need to clean it up on signals.
47  if ("_" != m_Path.native())
48    llvm::sys::DontRemoveFileOnSignal(m_Path.native());
49}
50
51//===----------------------------------------------------------------------===//
52// ToolOutputFile
53//===----------------------------------------------------------------------===//
54ToolOutputFile::ToolOutputFile(const sys::fs::Path& pPath,
55                               FileHandle::OpenMode pMode,
56                               FileHandle::Permission pPermission)
57  : m_Installer(pPath),
58    m_pFdOstream(NULL),
59    m_pFormattedOstream(NULL) {
60
61  if (!m_FileHandle.open(pPath, pMode, pPermission)) {
62    // If open fails, no clean-up is needed.
63    m_Installer.Keep = true;
64    fatal(diag::err_cannot_open_output_file)
65      << pPath
66      << sys::strerror(m_FileHandle.error());
67    return;
68  }
69}
70
71ToolOutputFile::~ToolOutputFile()
72{
73  if (m_pFormattedOstream != NULL)
74    delete m_pFormattedOstream;
75  if (m_pFdOstream != NULL)
76    delete m_pFdOstream;
77}
78
79void ToolOutputFile::keep()
80{
81  m_Installer.Keep = true;
82}
83
84/// os - Return the containeed raw_fd_ostream.
85/// Since os is rarely used, we lazily initialize it.
86llvm::raw_fd_ostream& ToolOutputFile::os()
87{
88  if (m_pFdOstream == NULL) {
89    assert(m_FileHandle.isOpened() &&
90           m_FileHandle.isGood() &&
91           m_FileHandle.isWritable());
92    m_pFdOstream = new llvm::raw_fd_ostream(m_FileHandle.handler(), false);
93  }
94  return *m_pFdOstream;
95}
96
97/// formatted_os - Return the contained formatted_raw_ostream
98llvm::formatted_raw_ostream& ToolOutputFile::formatted_os()
99{
100  if (m_pFormattedOstream == NULL) {
101    m_pFormattedOstream = new llvm::formatted_raw_ostream(os());
102  }
103  return *m_pFormattedOstream;
104}
105