summaryrefslogtreecommitdiffstats
path: root/lib/Utils/DebugDump.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Utils/DebugDump.cpp')
-rw-r--r--lib/Utils/DebugDump.cpp208
1 files changed, 77 insertions, 131 deletions
diff --git a/lib/Utils/DebugDump.cpp b/lib/Utils/DebugDump.cpp
index ec9e4703..ba11d965 100644
--- a/lib/Utils/DebugDump.cpp
+++ b/lib/Utils/DebugDump.cpp
@@ -39,9 +39,16 @@ static bool isdigit_str(const char *str)
return true;
}
-static std::string RemoveBackSlashes(const std::string& pDir);
+static std::string RemoveBackSlashes(const char *pDir)
+{
+ unsigned len = strlen(pDir);
+ while (len != 0 && pDir[len-1] == '/')
+ len--;
+ return std::string(pDir, len);
+}
+
static bool ExistFileDir(const char* pPath);
-static void LoadTextFile(const std::string& pPath, std::string& pData);
+static void LoadTextFile(const char *pPath, std::string& pData);
CDebugDump::CDebugDump() :
m_sDebugDumpDir(""),
@@ -50,7 +57,7 @@ CDebugDump::CDebugDump() :
m_bLocked(false)
{}
-void CDebugDump::Open(const std::string& pDir)
+void CDebugDump::Open(const char *pDir)
{
if (m_bOpened)
{
@@ -59,7 +66,7 @@ void CDebugDump::Open(const std::string& pDir)
m_sDebugDumpDir = RemoveBackSlashes(pDir);
if (!ExistFileDir(m_sDebugDumpDir.c_str()))
{
- throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::CDebugDump(): "+m_sDebugDumpDir+" does not exist.");
+ throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::CDebugDump(): " + m_sDebugDumpDir + " does not exist.");
}
Lock();
m_bOpened = true;
@@ -208,17 +215,17 @@ void CDebugDump::UnLock()
}
}
-void CDebugDump::Create(const std::string& pDir, int64_t uid)
+void CDebugDump::Create(const char *pDir, int64_t uid)
{
if (m_bOpened)
{
- throw CABRTException(EXCEP_ERROR, "CDebugDump::CDebugDump(): DebugDump is already opened.");
+ throw CABRTException(EXCEP_ERROR, "DebugDump is already opened");
}
m_sDebugDumpDir = RemoveBackSlashes(pDir);
if (ExistFileDir(m_sDebugDumpDir.c_str()))
{
- throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::CDebugDump(): "+m_sDebugDumpDir+" already exists.");
+ throw CABRTException(EXCEP_DD_OPEN, ssprintf("'%s' already exists", m_sDebugDumpDir.c_str()));
}
Lock();
@@ -228,13 +235,13 @@ void CDebugDump::Create(const std::string& pDir, int64_t uid)
{
UnLock();
m_bOpened = false;
- throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::Create(): Cannot create dir: " + pDir);
+ throw CABRTException(EXCEP_DD_OPEN, ssprintf("Can't create dir '%s'", pDir));
}
if (chmod(m_sDebugDumpDir.c_str(), 0700) == -1)
{
UnLock();
m_bOpened = false;
- throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::Create(): Cannot change permissions, dir: " + pDir);
+ throw CABRTException(EXCEP_DD_OPEN, ssprintf("Can't change mode of '%s'", pDir));
}
struct passwd* pw = getpwuid(uid);
gid_t gid = pw ? pw->pw_gid : uid;
@@ -245,14 +252,15 @@ void CDebugDump::Create(const std::string& pDir, int64_t uid)
perror_msg("can't change '%s' ownership to %u:%u", m_sDebugDumpDir.c_str(), (int)uid, (int)gid);
}
- SaveText(FILENAME_UID, ssprintf("%li", uid));
+ SaveText(FILENAME_UID, to_string(uid).c_str());
SaveKernelArchitectureRelease();
- SaveTime();
+ time_t t = time(NULL);
+ SaveText(FILENAME_TIME, to_string(t).c_str());
}
-static void DeleteFileDir(const std::string& pDir)
+static void DeleteFileDir(const char *pDir)
{
- DIR *dir = opendir(pDir.c_str());
+ DIR *dir = opendir(pDir);
if (!dir)
return;
@@ -261,26 +269,33 @@ static void DeleteFileDir(const std::string& pDir)
{
if (dot_or_dotdot(dent->d_name))
continue;
- std::string fullPath = pDir + "/" + dent->d_name;
+ std::string fullPath = concat_path_file(pDir, dent->d_name);
if (unlink(fullPath.c_str()) == -1)
{
if (errno != EISDIR)
{
closedir(dir);
- throw CABRTException(EXCEP_DD_DELETE, std::string(__func__) + ": Cannot remove file: " + fullPath);
+ throw CABRTException(EXCEP_DD_DELETE, ssprintf("Can't remove dir %s", fullPath.c_str()));
}
- DeleteFileDir(fullPath);
+ DeleteFileDir(fullPath.c_str());
}
}
closedir(dir);
- if (remove(pDir.c_str()) == -1)
+ if (remove(pDir) == -1)
{
- throw CABRTException(EXCEP_DD_DELETE, std::string(__func__) + ": Cannot remove dir: " + pDir);
+ throw CABRTException(EXCEP_DD_DELETE, ssprintf("Can't remove dir %s", pDir));
}
}
static bool IsTextFile(const char *name)
{
+ /* Some files in our dump directories are known to always be textual */
+ if (strcmp(name, "backtrace") == 0
+ || strcmp(name, "cmdline") == 0
+ ) {
+ return true;
+ }
+
/* This idiotic library thinks that file containing just "0" is not text (!!)
magic_t m = magic_open(MAGIC_MIME_TYPE);
@@ -320,25 +335,22 @@ static bool IsTextFile(const char *name)
int r = full_read(fd, buf, sizeof(buf));
close(fd);
+ /* Every once in a while, even a text file contains a few garbled
+ * or unexpected non-ASCII chars. We should not declare it "binary".
+ */
+ const unsigned RATIO = 50;
+ unsigned total_chars = r + RATIO;
+ unsigned bad_chars = 1; /* 1 prevents division by 0 later */
while (--r >= 0)
{
- if (buf[r] >= 0x7f)
- return false;
- /* Among control chars, only '\t','\n' etc are allowed */
- if (buf[r] < ' ' && !isspace(buf[r]))
- return false;
- }
- return true;
-}
-
-static std::string RemoveBackSlashes(const std::string& pDir)
-{
- std::string ret = pDir;
- while (ret[ret.length() - 1] == '/')
- {
- ret = ret.substr(0, ret.length() - 2);
+ if (buf[r] >= 0x7f
+ /* among control chars, only '\t','\n' etc are allowed */
+ || (buf[r] < ' ' && !isspace(buf[r]))
+ ) {
+ bad_chars++;
+ }
}
- return ret;
+ return (total_chars / bad_chars) >= RATIO;
}
void CDebugDump::Delete()
@@ -347,7 +359,7 @@ void CDebugDump::Delete()
{
return;
}
- DeleteFileDir(m_sDebugDumpDir);
+ DeleteFileDir(m_sDebugDumpDir.c_str());
}
void CDebugDump::Close()
@@ -374,100 +386,44 @@ void CDebugDump::SaveKernelArchitectureRelease()
const char *release_ptr = release.c_str();
unsigned len_1st_str = strchrnul(release_ptr, '\n') - release_ptr;
release.erase(len_1st_str); /* usually simply removes trailing '\n' */
- SaveText(FILENAME_RELEASE, release);
+ SaveText(FILENAME_RELEASE, release.c_str());
}
-void CDebugDump::SaveTime()
+static void LoadTextFile(const char *pPath, std::string& pData)
{
- time_t t = time(NULL);
- SaveText(FILENAME_TIME, to_string(t));
-}
-
-static void LoadTextFile(const std::string& pPath, std::string& pData)
-{
- std::ifstream fIn;
+ FILE *fp = fopen(pPath, "r");
+ if (!fp)
+ {
+ throw CABRTException(EXCEP_DD_LOAD, ssprintf("Can't open file '%s'", pPath));
+ }
pData = "";
- fIn.open(pPath.c_str());
- if (fIn.is_open())
+ int ch;
+ while ((ch = fgetc(fp)) != EOF)
{
- // TODO: rewrite this
- int ch;
- while ((ch = fIn.get())!= EOF)
+ if (ch == '\0')
{
- if (ch == 0)
- {
- pData += " ";
- }
- else if (isspace(ch) || (isascii(ch) && !iscntrl(ch)))
- {
- pData += ch;
- }
+ pData += ' ';
}
- fIn.close();
- }
- else
- {
- throw CABRTException(EXCEP_DD_LOAD, std::string(__func__) + ": Cannot open file " + pPath);
- }
-}
-
-static void LoadBinaryFile(const std::string& pPath, char** pData, unsigned int* pSize)
-{
- std::ifstream fIn;
- fIn.open(pPath.c_str(), std::ios::binary | std::ios::ate);
- unsigned int size;
- if (fIn.is_open())
- {
- size = fIn.tellg();
- char *data = new char [size];
- fIn.read(data, size);
-
- *pData = data;
- *pSize = size;
-
- fIn.close();
- }
- else
- {
- throw CABRTException(EXCEP_DD_LOAD, std::string(__func__) + ": Cannot open file " + pPath);
- }
-}
-
-static void SaveTextFile(const std::string& pPath, const std::string& pData)
-{
- std::ofstream fOut;
- fOut.open(pPath.c_str());
- if (fOut.is_open())
- {
- fOut << pData;
- if (!fOut.good())
+ else if (isspace(ch) || (isascii(ch) && !iscntrl(ch)))
{
- throw CABRTException(EXCEP_DD_SAVE, std::string(__func__) + ": Cannot save file " + pPath);
+ pData += ch;
}
- fOut.close();
- }
- else
- {
- throw CABRTException(EXCEP_DD_SAVE, std::string(__func__) + ": Cannot open file " + pPath);
}
+ fclose(fp);
}
-static void SaveBinaryFile(const std::string& pPath, const char* pData, const unsigned pSize)
+static void SaveBinaryFile(const char *pPath, const char* pData, unsigned pSize)
{
- std::ofstream fOut;
- fOut.open(pPath.c_str(), std::ios::binary);
- if (fOut.is_open())
+ int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+ if (fd < 0)
{
- fOut.write(pData, pSize);
- if (!fOut.good())
- {
- throw CABRTException(EXCEP_DD_SAVE, std::string(__func__) + ": Cannot save file " + pPath);
- }
- fOut.close();
+ throw CABRTException(EXCEP_DD_SAVE, ssprintf("Can't open file '%s'", pPath));
}
- else
+ unsigned r = full_write(fd, pData, pSize);
+ close(fd);
+ if (r != pSize)
{
- throw CABRTException(EXCEP_DD_SAVE, std::string(__func__) + ": Cannot open file " + pPath);
+ throw CABRTException(EXCEP_DD_SAVE, ssprintf("Can't save file '%s'", pPath));
}
}
@@ -477,36 +433,27 @@ void CDebugDump::LoadText(const char* pName, std::string& pData)
{
throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::LoadText(): DebugDump is not opened.");
}
- std::string fullPath = m_sDebugDumpDir + "/" + pName;
- LoadTextFile(fullPath, pData);
-}
-void CDebugDump::LoadBinary(const char* pName, char** pData, unsigned int* pSize)
-{
- if (!m_bOpened)
- {
- throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::LoadBinary(): DebugDump is not opened.");
- }
- std::string fullPath = m_sDebugDumpDir + "/" + pName;
- LoadBinaryFile(fullPath, pData, pSize);
+ std::string fullPath = m_sDebugDumpDir + '/' + pName;
+ LoadTextFile(fullPath.c_str(), pData);
}
-void CDebugDump::SaveText(const char* pName, const std::string& pData)
+void CDebugDump::SaveText(const char* pName, const char* pData)
{
if (!m_bOpened)
{
throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::SaveText(): DebugDump is not opened.");
}
std::string fullPath = m_sDebugDumpDir + "/" + pName;
- SaveTextFile(fullPath, pData);
+ SaveBinaryFile(fullPath.c_str(), pData, strlen(pData));
}
-void CDebugDump::SaveBinary(const char* pName, const char* pData, const unsigned int pSize)
+void CDebugDump::SaveBinary(const char* pName, const char* pData, unsigned pSize)
{
if (!m_bOpened)
{
throw CABRTException(EXCEP_DD_OPEN, "CDebugDump::SaveBinary(): DebugDump is not opened.");
}
std::string fullPath = m_sDebugDumpDir + "/" + pName;
- SaveBinaryFile(fullPath, pData, pSize);
+ SaveBinaryFile(fullPath.c_str(), pData, pSize);
}
void CDebugDump::InitGetNextFile()
@@ -538,7 +485,7 @@ bool CDebugDump::GetNextFile(std::string& pFileName, std::string& pContent, bool
{
if (is_regular_file(dent, m_sDebugDumpDir.c_str()))
{
- std::string fullname = m_sDebugDumpDir + "/" + dent->d_name;
+ std::string fullname = concat_path_file(m_sDebugDumpDir.c_str(), dent->d_name);
pFileName = dent->d_name;
if (IsTextFile(fullname.c_str()))
@@ -548,7 +495,7 @@ bool CDebugDump::GetNextFile(std::string& pFileName, std::string& pContent, bool
}
else
{
- pContent = "";
+ pContent.clear();
pIsTextFile = false;
}
return true;
@@ -558,4 +505,3 @@ bool CDebugDump::GetNextFile(std::string& pFileName, std::string& pContent, bool
m_pGetNextFileDir = NULL;
return false;
}
-