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
23 using namespace mcld;
24
25 //===----------------------------------------------------------------------===//
26 // CleanupInstaller
27 //===----------------------------------------------------------------------===//
CleanupInstaller(const sys::fs::Path & pPath)28 ToolOutputFile::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
~CleanupInstaller()35 ToolOutputFile::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 //===----------------------------------------------------------------------===//
ToolOutputFile(const sys::fs::Path & pPath,FileHandle::OpenMode pMode,FileHandle::Permission pPermission)54 ToolOutputFile::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
~ToolOutputFile()71 ToolOutputFile::~ToolOutputFile()
72 {
73 if (m_pFormattedOstream != NULL)
74 delete m_pFormattedOstream;
75 if (m_pFdOstream != NULL)
76 delete m_pFdOstream;
77 }
78
keep()79 void 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.
os()86 llvm::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
formatted_os()98 llvm::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