Skip to content

Commit 56682d6

Browse files
authored
determine log file location (#3)
1 parent 4b412e7 commit 56682d6

File tree

4 files changed

+101
-7
lines changed

4 files changed

+101
-7
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CXXFLAGS=-Wall -Wextra -Wpedantic
1+
CXXFLAGS=-Wall -Wextra -Wpedantic -std=c++17
22
SRC=main.cpp\
33
config.cpp
44
OBJ=$(SRC:%.cpp=%.o)

config.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66
#include <cstring>
77
#include <cerrno>
88

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+
918
std::string Config::load(const std::filesystem::path &path)
1019
{
1120
// Read config file
@@ -57,6 +66,22 @@ std::string Config::load(const std::filesystem::path &path)
5766
continue;
5867
}
5968

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+
6085
if (key == "args") {
6186
if (!value.is<picojson::array>())
6287
return "Invalid value type for '" + key + "'";
@@ -136,6 +161,11 @@ std::string Config::parseArgs(int argc, char **argv)
136161
if (m_filename.empty())
137162
return "Missing filename";
138163

164+
if (m_logFilePath.empty()) {
165+
const std::string error = getDefaultLogFilePath(m_logFilePath);
166+
if (!error.empty())
167+
return error;
168+
}
139169
if (configPath.empty())
140170
configPath = findConfig(m_filename);
141171

@@ -167,3 +197,53 @@ std::filesystem::path Config::findConfig(const std::filesystem::path &input_path
167197

168198
return "";
169199
}
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+
}

config.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ class Config {
99
public:
1010
Config()
1111
: m_projectFilePath("")
12-
, m_filename("")
12+
, m_logFilePath("")
13+
, m_loggingEnabled(true)
1314
, m_cppcheck("cppcheck")
15+
, m_filename("")
1416
, m_args({})
1517
{
1618
}
@@ -28,12 +30,20 @@ class Config {
2830
* on failure. */
2931
std::string parseArgs(int argc, char **argv);
3032

33+
const std::filesystem::path logFilePath() const
34+
{
35+
return m_logFilePath;
36+
}
37+
3138
private:
3239
static std::filesystem::path findConfig(const std::filesystem::path &input_path);
40+
static std::string getDefaultLogFilePath(std::filesystem::path &path);
3341

34-
std::filesystem::path m_projectFilePath = "";
35-
std::filesystem::path m_filename;
42+
std::filesystem::path m_projectFilePath;
43+
std::filesystem::path m_logFilePath;
44+
bool m_loggingEnabled;
3645
std::string m_cppcheck;
46+
std::filesystem::path m_filename;
3747
std::vector<std::string> m_args;
3848
};
3949

main.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ static int executeCommand(const std::string& cmd, std::string &output)
5959

6060
int main(int argc, char** argv) {
6161

62-
const std::string log_path = std::filesystem::current_path() / "log.txt";
63-
logfile.open(log_path, std::ios_base::app);
6462

6563
Config config;
6664

@@ -70,9 +68,15 @@ int main(int argc, char** argv) {
7068
return EXIT_FAILURE;
7169
}
7270

71+
logfile.open(config.logFilePath(), std::ios_base::app);
72+
if (logfile.bad()) {
73+
std::cerr << "error: Failed to open logfile at '" << config.logFilePath().string() << "'" << std::endl;
74+
return EXIT_FAILURE;
75+
}
76+
7377
const std::string cmd = config.command();
7478

75-
logfile << "CMD:" << cmd << std::endl;
79+
logfile << "CMD: " << cmd << std::endl;
7680

7781
std::string output;
7882
int res = executeCommand(cmd, output);

0 commit comments

Comments
 (0)