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