summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/client/crashreporter_unix_common.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/crashreporter/client/crashreporter_unix_common.cpp')
-rw-r--r--toolkit/crashreporter/client/crashreporter_unix_common.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/toolkit/crashreporter/client/crashreporter_unix_common.cpp b/toolkit/crashreporter/client/crashreporter_unix_common.cpp
new file mode 100644
index 0000000000..e6514d4423
--- /dev/null
+++ b/toolkit/crashreporter/client/crashreporter_unix_common.cpp
@@ -0,0 +1,139 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "crashreporter.h"
+
+#include <algorithm>
+#include <sys/wait.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+using namespace CrashReporter;
+using std::ios_base;
+using std::sort;
+using std::string;
+using std::vector;
+
+struct FileData {
+ time_t timestamp;
+ string path;
+};
+
+static bool CompareFDTime(const FileData& fd1, const FileData& fd2) {
+ return fd1.timestamp > fd2.timestamp;
+}
+
+void UIPruneSavedDumps(const string& directory) {
+ DIR* dirfd = opendir(directory.c_str());
+ if (!dirfd) return;
+
+ vector<FileData> dumpfiles;
+
+ while (dirent* dir = readdir(dirfd)) {
+ FileData fd;
+ fd.path = directory + '/' + dir->d_name;
+ if (fd.path.size() < 5) continue;
+
+ if (fd.path.compare(fd.path.size() - 4, 4, ".dmp") != 0) continue;
+
+ struct stat st;
+ if (stat(fd.path.c_str(), &st)) {
+ closedir(dirfd);
+ return;
+ }
+
+ fd.timestamp = st.st_mtime;
+
+ dumpfiles.push_back(fd);
+ }
+
+ closedir(dirfd);
+
+ sort(dumpfiles.begin(), dumpfiles.end(), CompareFDTime);
+
+ while (dumpfiles.size() > kSaveCount) {
+ // get the path of the oldest file
+ string path = dumpfiles[dumpfiles.size() - 1].path;
+ UIDeleteFile(path);
+
+ // s/.dmp/.extra/
+ path.replace(path.size() - 4, 4, ".extra");
+ UIDeleteFile(path);
+
+ dumpfiles.pop_back();
+ }
+}
+
+bool UIRunProgram(const string& exename, const vector<string>& args,
+ bool wait) {
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ return false;
+ } else if (pid == 0) {
+ // Child
+ size_t argvLen = args.size() + 2;
+ vector<char*> argv(argvLen);
+
+ argv[0] = const_cast<char*>(exename.c_str());
+
+ for (size_t i = 0; i < args.size(); i++) {
+ argv[i + 1] = const_cast<char*>(args[i].c_str());
+ }
+
+ argv[argvLen - 1] = nullptr;
+
+ // Run the program
+ int rv = execv(exename.c_str(), argv.data());
+
+ if (rv == -1) {
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ // Parent
+ if (wait) {
+ waitpid(pid, nullptr, 0);
+ }
+ }
+
+ return true;
+}
+
+bool UIEnsurePathExists(const string& path) {
+ int ret = mkdir(path.c_str(), S_IRWXU);
+ int e = errno;
+ if (ret == -1 && e != EEXIST) return false;
+
+ return true;
+}
+
+bool UIFileExists(const string& path) {
+ struct stat sb;
+ int ret = stat(path.c_str(), &sb);
+ if (ret == -1 || !(sb.st_mode & S_IFREG)) return false;
+
+ return true;
+}
+
+bool UIDeleteFile(const string& file) { return (unlink(file.c_str()) != -1); }
+
+std::ifstream* UIOpenRead(const string& filename, ios_base::openmode mode) {
+ return new std::ifstream(filename.c_str(), mode);
+}
+
+std::ofstream* UIOpenWrite(const string& filename, ios_base::openmode mode) {
+ return new std::ofstream(filename.c_str(), mode);
+}
+
+string UIGetEnv(const string& name) {
+ const char* var = getenv(name.c_str());
+ if (var && *var) {
+ return var;
+ }
+
+ return "";
+}