summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/client/crashreporter_unix_common.cpp
blob: 0cecc6262aeeccdbeecd2a8a8210bb850bcd9280 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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.c_str());

    // s/.dmp/.extra/
    path.replace(path.size() - 4, 4, ".extra");
    UIDeleteFile(path.c_str());

    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 "";
}