1 //===-- MIUtilFileStd.cpp ---------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
16 #include "MICmnResources.h"
17 #include "MIUtilFileStd.h"
18 #include "lldb/Host/FileSystem.h"
20 #include "llvm/Support/ConvertUTF.h"
21 #include "llvm/Support/Errno.h"
24 // Details: CMIUtilFileStd constructor.
30 CMIUtilFileStd::CMIUtilFileStd()
31 : m_fileNamePath(CMIUtilString()), m_pFileHandle(nullptr)
34 m_constCharNewLine("\r\n")
37 m_constCharNewLine("\n")
38 #endif // #if defined( _MSC_VER )
44 // Details: CMIUtilFileStd destructor.
50 CMIUtilFileStd::~CMIUtilFileStd() { Close(); }
53 // Details: Open file for writing. On the first call to this function after
55 // is created the file is either created or replace, from then on open
59 // Args: vFileNamePath - (R) File name path.
60 // vwrbNewCreated - (W) True - file recreated, false - file appended
62 // Return: MIstatus::success - Functional succeeded.
63 // MIstatus::failure - Functional failed.
66 bool CMIUtilFileStd::CreateWrite(const CMIUtilString &vFileNamePath,
67 bool &vwrbNewCreated) {
70 vwrbNewCreated = false;
72 if (vFileNamePath.empty()) {
74 SetErrorDescription(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME));
75 return MIstatus::failure;
78 // File is already open so exit
79 if (m_pFileHandle != nullptr)
80 return MIstatus::success;
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");
87 // Open a file with exclusive write and shared read permissions
89 if (llvm::ConvertUTF8toWide(vFileNamePath.c_str(), path))
90 m_pFileHandle = ::_wfsopen(path.c_str(), L"wb", _SH_DENYWR);
93 m_pFileHandle = nullptr;
95 #endif // !defined( _MSC_VER )
97 if (m_pFileHandle == nullptr) {
99 SetErrorDescriptionn(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE),
100 strerror(errno), vFileNamePath.c_str());
101 return MIstatus::failure;
104 vwrbNewCreated = true;
105 m_fileNamePath = vFileNamePath;
107 return MIstatus::success;
111 // Details: Write data to existing opened file.
113 // Args: vData - (R) Text data.
114 // Return: MIstatus::success - Functional succeeded.
115 // MIstatus::failure - Functional failed.
118 bool CMIUtilFileStd::Write(const CMIUtilString &vData) {
119 if (vData.size() == 0)
120 return MIstatus::success;
123 return MIstatus::failure;
125 if (m_pFileHandle == nullptr) {
127 SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN),
128 m_fileNamePath.c_str());
129 return MIstatus::failure;
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;
140 // Not all of the data has been transferred
142 SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE),
143 m_fileNamePath.c_str());
144 return MIstatus::failure;
148 // Details: Write data to existing opened file.
150 // Args: vData - (R) Text data.
151 // vCharCnt - (R) Text data length.
152 // Return: MIstatus::success - Functional succeeded.
153 // MIstatus::failure - Functional failed.
156 bool CMIUtilFileStd::Write(const char *vpData, const MIuint vCharCnt) {
158 return MIstatus::success;
161 return MIstatus::failure;
163 if (m_pFileHandle == nullptr) {
165 SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN),
166 m_fileNamePath.c_str());
167 return MIstatus::failure;
170 if (::fwrite(vpData, 1, vCharCnt, m_pFileHandle) == vCharCnt) {
171 // Flush the data to the file
172 ::fflush(m_pFileHandle);
173 return MIstatus::success;
176 // Not all of the data has been transferred
178 SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE),
179 m_fileNamePath.c_str());
180 return MIstatus::failure;
184 // Details: Close existing opened file. Note Close() must must an open!
190 void CMIUtilFileStd::Close() {
191 if (m_pFileHandle == nullptr)
194 ::fclose(m_pFileHandle);
195 m_pFileHandle = nullptr;
196 // m_bFileError = false; Do not reset as want to remain until next attempt at
201 // Details: Retrieve state of whether the file is ok.
204 // Return: True - file ok.
205 // False - file has a problem.
208 bool CMIUtilFileStd::IsOk() const { return !m_bFileError; }
211 // Details: Status on a file existing already.
213 // Args: vFileNamePath.
214 // Return: True - Exists.
215 // False - Not found.
218 bool CMIUtilFileStd::IsFileExist(const CMIUtilString &vFileNamePath) const {
219 if (vFileNamePath.empty())
222 FILE *pTmp = nullptr;
223 pTmp = llvm::sys::RetryAfterSignal(nullptr, ::fopen,
224 vFileNamePath.c_str(), "wb");
225 if (pTmp != nullptr) {
234 // Details: Retrieve the file current carriage line return characters used.
237 // Return: CMIUtilString & - Text.
240 const CMIUtilString &CMIUtilFileStd::GetLineReturn() const {
241 return m_constCharNewLine;
245 // Details: Given a file name directory path, strip off the filename and return
247 // It look for either backslash or forward slash.
249 // Args: vDirectoryPath - (R) Text directory path.
250 // Return: CMIUtilString - Directory path.
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;
263 const CMIUtilString strPath(vDirectoryPath.substr(0, nPos2).c_str());
268 // Details: Return either backslash or forward slash appropriate to the OS this
271 // Type: Static method.
273 // Return: char - '/' or '\' character.
276 char CMIUtilFileStd::GetSlash() {
277 #if !defined(_MSC_VER)
281 #endif // !defined( _MSC_VER )