|
6 | 6 | #include <cstring> |
7 | 7 | #include <cerrno> |
8 | 8 |
|
| 9 | +// mkdir and access |
| 10 | +#ifdef _WIN32 |
| 11 | +#include <direct.h> |
| 12 | +#include <io.h> |
| 13 | +#else |
| 14 | +#include <sys/stat.h> |
| 15 | +#include <unistd.h> |
| 16 | +#endif |
| 17 | + |
9 | 18 | std::string Config::load(const std::filesystem::path &path) |
10 | 19 | { |
11 | 20 | // Read config file |
@@ -57,6 +66,22 @@ std::string Config::load(const std::filesystem::path &path) |
57 | 66 | continue; |
58 | 67 | } |
59 | 68 |
|
| 69 | + if (key == "log_file") { |
| 70 | + if (!value.is<std::string>()) { |
| 71 | + return "Invalid value type for '" + key + "'"; |
| 72 | + } |
| 73 | + m_logFilePath = value.get<std::string>(); |
| 74 | + continue; |
| 75 | + } |
| 76 | + |
| 77 | + if (key == "enable_logging") { |
| 78 | + if (!value.is<bool>()) { |
| 79 | + return "Invalid value type for '" + key + "'"; |
| 80 | + } |
| 81 | + m_loggingEnabled = value.get<bool>(); |
| 82 | + continue; |
| 83 | + } |
| 84 | + |
60 | 85 | if (key == "args") { |
61 | 86 | if (!value.is<picojson::array>()) |
62 | 87 | return "Invalid value type for '" + key + "'"; |
@@ -136,6 +161,11 @@ std::string Config::parseArgs(int argc, char **argv) |
136 | 161 | if (m_filename.empty()) |
137 | 162 | return "Missing filename"; |
138 | 163 |
|
| 164 | + if (m_logFilePath.empty()) { |
| 165 | + const std::string error = getDefaultLogFilePath(m_logFilePath); |
| 166 | + if (!error.empty()) |
| 167 | + return error; |
| 168 | + } |
139 | 169 | if (configPath.empty()) |
140 | 170 | configPath = findConfig(m_filename); |
141 | 171 |
|
@@ -167,3 +197,53 @@ std::filesystem::path Config::findConfig(const std::filesystem::path &input_path |
167 | 197 |
|
168 | 198 | return ""; |
169 | 199 | } |
| 200 | + |
| 201 | +static std::string mkdirRecursive(const std::filesystem::path &path) |
| 202 | +{ |
| 203 | + int res; |
| 204 | + std::filesystem::path subpath = ""; |
| 205 | + for (auto dir : path) { |
| 206 | + subpath = subpath / dir; |
| 207 | +#ifdef _WIN32 |
| 208 | + res = _access(subpath.string().c_str(), 0) && _mkdir(subpath.string().c_str()); |
| 209 | +#else |
| 210 | + res = access(subpath.string().c_str(), F_OK) && mkdir(subpath.string().c_str(), 0777); |
| 211 | +#endif |
| 212 | + if (res) |
| 213 | + return "Failed to create '" + subpath.string() + "': " + std::strerror(errno); |
| 214 | + } |
| 215 | + return ""; |
| 216 | +} |
| 217 | + |
| 218 | +std::string Config::getDefaultLogFilePath(std::filesystem::path &path) |
| 219 | +{ |
| 220 | + path = ""; |
| 221 | + |
| 222 | +#ifdef _WIN32 |
| 223 | + const char *localappdata = std::getenv("LOCALAPPDATA"); |
| 224 | + |
| 225 | + if (localappdata) { |
| 226 | + path = localappdata; |
| 227 | + } else { |
| 228 | + return "%LOCALAPPDATA% not set"; |
| 229 | + } |
| 230 | +#else |
| 231 | + const char *xdg_state_home = std::getenv("XDG_STATE_HOME"); |
| 232 | + |
| 233 | + if (xdg_state_home) { |
| 234 | + path = xdg_state_home; |
| 235 | + } else { |
| 236 | + path = std::string(std::getenv("HOME")) + "/.local/state"; |
| 237 | + } |
| 238 | +#endif |
| 239 | + |
| 240 | + path = path / "run-cppcheck"; |
| 241 | + |
| 242 | + const std::string error = mkdirRecursive(path); |
| 243 | + if (!error.empty()) |
| 244 | + return error; |
| 245 | + |
| 246 | + path = path / "log.txt"; |
| 247 | + |
| 248 | + return ""; |
| 249 | +} |
0 commit comments