diff options
Diffstat (limited to 'lib/Utils/DebugDump.cpp')
-rw-r--r-- | lib/Utils/DebugDump.cpp | 208 |
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; } - |