]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/tools/lldb-mi/MIUtilFileStd.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / tools / lldb-mi / MIUtilFileStd.cpp
1 //===-- MIUtilFileStd.cpp ---------------------------------------*- C++ -*-===//
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 // Third party headers
11 #include <assert.h>
12 #include <cerrno>
13 #include <stdio.h>
14 #include <string.h>
15
16 // In-house headers:
17 #include "MICmnResources.h"
18 #include "MIUtilFileStd.h"
19 #include "lldb/Host/FileSystem.h"
20
21 #include "llvm/Support/ConvertUTF.h"
22
23 //++
24 //------------------------------------------------------------------------------------
25 // Details: CMIUtilFileStd constructor.
26 // Type:    Method.
27 // Args:    None.
28 // Return:  None.
29 // Throws:  None.
30 //--
31 CMIUtilFileStd::CMIUtilFileStd()
32     : m_fileNamePath(CMIUtilString()), m_pFileHandle(nullptr)
33 #if defined(_MSC_VER)
34       ,
35       m_constCharNewLine("\r\n")
36 #else
37       ,
38       m_constCharNewLine("\n")
39 #endif // #if defined( _MSC_VER )
40       ,
41       m_bFileError(false) {
42 }
43
44 //++
45 //------------------------------------------------------------------------------------
46 // Details: CMIUtilFileStd destructor.
47 // Type:    Method.
48 // Args:    None.
49 // Return:  None.
50 // Throws:  None.
51 //--
52 CMIUtilFileStd::~CMIUtilFileStd() { Close(); }
53
54 //++
55 //------------------------------------------------------------------------------------
56 // Details: Open file for writing. On the first call to this function after
57 // *this object
58 //          is created the file is either created or replace, from then on open
59 //          only opens
60 //          an existing file.
61 // Type:    Method.
62 // Args:    vFileNamePath   - (R) File name path.
63 //          vwrbNewCreated  - (W) True - file recreated, false - file appended
64 //          too.
65 // Return:  MIstatus::success - Functional succeeded.
66 //          MIstatus::failure - Functional failed.
67 // Throws:  None.
68 //--
69 bool CMIUtilFileStd::CreateWrite(const CMIUtilString &vFileNamePath,
70                                  bool &vwrbNewCreated) {
71   // Reset
72   m_bFileError = false;
73   vwrbNewCreated = false;
74
75   if (vFileNamePath.empty()) {
76     m_bFileError = true;
77     SetErrorDescription(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME));
78     return MIstatus::failure;
79   }
80
81   // File is already open so exit
82   if (m_pFileHandle != nullptr)
83     return MIstatus::success;
84
85 #if !defined(_MSC_VER)
86   // Open with 'write' and 'binary' mode
87   m_pFileHandle = ::fopen(vFileNamePath.c_str(), "wb");
88 #else
89   // Open a file with exclusive write and shared read permissions
90   std::wstring path;
91   if (llvm::ConvertUTF8toWide(vFileNamePath.c_str(), path))
92     m_pFileHandle = ::_wfsopen(path.c_str(), L"wb", _SH_DENYWR);
93   else {
94     errno = EINVAL;
95     m_pFileHandle = nullptr;
96   }
97 #endif // !defined( _MSC_VER )
98
99   if (m_pFileHandle == nullptr) {
100     m_bFileError = true;
101     SetErrorDescriptionn(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE),
102                          strerror(errno), vFileNamePath.c_str());
103     return MIstatus::failure;
104   }
105
106   vwrbNewCreated = true;
107   m_fileNamePath = vFileNamePath;
108
109   return MIstatus::success;
110 }
111
112 //++
113 //------------------------------------------------------------------------------------
114 // Details: Write data to existing opened file.
115 // Type:    Method.
116 // Args:    vData - (R) Text data.
117 // Return:  MIstatus::success - Functional succeeded.
118 //          MIstatus::failure - Functional failed.
119 // Throws:  None.
120 //--
121 bool CMIUtilFileStd::Write(const CMIUtilString &vData) {
122   if (vData.size() == 0)
123     return MIstatus::success;
124
125   if (m_bFileError)
126     return MIstatus::failure;
127
128   if (m_pFileHandle == nullptr) {
129     m_bFileError = true;
130     SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN),
131                          m_fileNamePath.c_str());
132     return MIstatus::failure;
133   }
134
135   // Get the string size
136   MIuint size = vData.size();
137   if (::fwrite(vData.c_str(), 1, size, m_pFileHandle) == size) {
138     // Flush the data to the file
139     ::fflush(m_pFileHandle);
140     return MIstatus::success;
141   }
142
143   // Not all of the data has been transferred
144   m_bFileError = true;
145   SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE),
146                        m_fileNamePath.c_str());
147   return MIstatus::failure;
148 }
149
150 //++
151 //------------------------------------------------------------------------------------
152 // Details: Write data to existing opened file.
153 // Type:    Method.
154 // Args:    vData       - (R) Text data.
155 //          vCharCnt    - (R) Text data length.
156 // Return:  MIstatus::success - Functional succeeded.
157 //          MIstatus::failure - Functional failed.
158 // Throws:  None.
159 //--
160 bool CMIUtilFileStd::Write(const char *vpData, const MIuint vCharCnt) {
161   if (vCharCnt == 0)
162     return MIstatus::success;
163
164   if (m_bFileError)
165     return MIstatus::failure;
166
167   if (m_pFileHandle == nullptr) {
168     m_bFileError = true;
169     SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN),
170                          m_fileNamePath.c_str());
171     return MIstatus::failure;
172   }
173
174   if (::fwrite(vpData, 1, vCharCnt, m_pFileHandle) == vCharCnt) {
175     // Flush the data to the file
176     ::fflush(m_pFileHandle);
177     return MIstatus::success;
178   }
179
180   // Not all of the data has been transferred
181   m_bFileError = true;
182   SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE),
183                        m_fileNamePath.c_str());
184   return MIstatus::failure;
185 }
186
187 //++
188 //------------------------------------------------------------------------------------
189 // Details: Close existing opened file. Note Close() must must an open!
190 // Type:    Method.
191 // Args:    None.
192 // Return:  None.
193 // Throws:  None.
194 //--
195 void CMIUtilFileStd::Close() {
196   if (m_pFileHandle == nullptr)
197     return;
198
199   ::fclose(m_pFileHandle);
200   m_pFileHandle = nullptr;
201   // m_bFileError = false; Do not reset as want to remain until next attempt at
202   // open or create
203 }
204
205 //++
206 //------------------------------------------------------------------------------------
207 // Details: Retrieve state of whether the file is ok.
208 // Type:    Method.
209 // Args:    None.
210 // Return:  True - file ok.
211 //          False - file has a problem.
212 // Throws:  None.
213 //--
214 bool CMIUtilFileStd::IsOk() const { return !m_bFileError; }
215
216 //++
217 //------------------------------------------------------------------------------------
218 // Details: Status on a file existing already.
219 // Type:    Method.
220 // Args:    vFileNamePath.
221 // Return:  True - Exists.
222 //          False - Not found.
223 // Throws:  None.
224 //--
225 bool CMIUtilFileStd::IsFileExist(const CMIUtilString &vFileNamePath) const {
226   if (vFileNamePath.empty())
227     return false;
228
229   FILE *pTmp = nullptr;
230   pTmp = ::fopen(vFileNamePath.c_str(), "wb");
231   if (pTmp != nullptr) {
232     ::fclose(pTmp);
233     return true;
234   }
235
236   return false;
237 }
238
239 //++
240 //------------------------------------------------------------------------------------
241 // Details: Retrieve the file current carriage line return characters used.
242 // Type:    Method.
243 // Args:    None.
244 // Return:  CMIUtilString & - Text.
245 // Throws:  None.
246 //--
247 const CMIUtilString &CMIUtilFileStd::GetLineReturn() const {
248   return m_constCharNewLine;
249 }
250
251 //++
252 //------------------------------------------------------------------------------------
253 // Details: Given a file name directory path, strip off the filename and return
254 // the path.
255 //          It look for either backslash or forward slash.
256 // Type:    Method.
257 // Args:    vDirectoryPath  - (R) Text directory path.
258 // Return:  CMIUtilString - Directory path.
259 // Throws:  None.
260 //--
261 CMIUtilString
262 CMIUtilFileStd::StripOffFileName(const CMIUtilString &vDirectoryPath) {
263   const size_t nPos = vDirectoryPath.rfind('\\');
264   size_t nPos2 = vDirectoryPath.rfind('/');
265   if ((nPos == std::string::npos) && (nPos2 == std::string::npos))
266     return vDirectoryPath;
267
268   if (nPos > nPos2)
269     nPos2 = nPos;
270
271   const CMIUtilString strPath(vDirectoryPath.substr(0, nPos2).c_str());
272   return strPath;
273 }
274
275 //++
276 //------------------------------------------------------------------------------------
277 // Details: Return either backslash or forward slash appropriate to the OS this
278 // application
279 //          is running on.
280 // Type:    Static method.
281 // Args:    None.
282 // Return:  char - '/' or '\' character.
283 // Throws:  None.
284 //--
285 char CMIUtilFileStd::GetSlash() {
286 #if !defined(_MSC_VER)
287   return '/';
288 #else
289   return '\\';
290 #endif // !defined( _MSC_VER )
291 }