diff --git a/common/daemon.cpp b/common/daemon.cpp index dc2c4b91..502da8cb 100644 --- a/common/daemon.cpp +++ b/common/daemon.cpp @@ -30,6 +30,7 @@ #include #include "common/snapException.h" #include "common/strCompat.h" +#include "common/utils/file_utils.h" #include "common/utils.h" @@ -54,7 +55,7 @@ Daemon::~Daemon() void Daemon::daemonize() { std::string pidfileDir(pidfile_.substr(0, pidfile_.find_last_of('/'))); - mkdirRecursive(pidfileDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + utils::file::mkdirRecursive(pidfileDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); /// Ensure only one copy pidFilehandle_ = open(pidfile_.c_str(), O_RDWR|O_CREAT, 0644); diff --git a/common/utils.h b/common/utils.h index f4ed774c..15a70419 100644 --- a/common/utils.h +++ b/common/utils.h @@ -55,22 +55,6 @@ namespace strutils = utils::string; -static int mkdirRecursive(const char *path, mode_t mode) -{ - std::vector pathes = strutils::split(path, '/'); - std::stringstream ss; - int res = 0; - for (const auto& p: pathes) - { - if (p.empty()) - continue; - ss << "/" << p; - int res = mkdir(ss.str().c_str(), mode); - if ((res != 0) && (errno != EEXIST)) - return res; - } - return res; -} static std::string execGetOutput(const std::string& cmd) diff --git a/common/utils/file_utils.h b/common/utils/file_utils.h new file mode 100644 index 00000000..95e765ff --- /dev/null +++ b/common/utils/file_utils.h @@ -0,0 +1,77 @@ +/*** + This file is part of snapcast + Copyright (C) 2014-2017 Johannes Pohl + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***/ + +#ifndef FILE_UTILS_H +#define FILE_UTILS_H + +#include +#include +#include +#include +#include "common/utils/string_utils.h" + + +namespace utils +{ +namespace file +{ + +static void do_chown(const std::string& file_path, const std::string& user_name, const std::string& group_name) +{ + uid_t uid; + gid_t gid; + struct passwd *pwd; + struct group *grp; + + pwd = getpwnam(user_name.c_str()); + if (pwd == NULL) + throw std::runtime_error("Failed to get uid"); + uid = pwd->pw_uid; + + grp = getgrnam(group_name.c_str()); + if (grp == NULL) + throw std::runtime_error("Failed to get gid"); + gid = grp->gr_gid; + + if (chown(file_path.c_str(), uid, gid) == -1) + throw std::runtime_error("chown failed"); +} + + +static int mkdirRecursive(const char *path, mode_t mode) +{ + std::vector pathes = utils::string::split(path, '/'); + std::stringstream ss; + int res = 0; + for (const auto& p: pathes) + { + if (p.empty()) + continue; + ss << "/" << p; + int res = mkdir(ss.str().c_str(), mode); + if ((res != 0) && (errno != EEXIST)) + return res; + } + return res; +} + +} // namespace file +} // namespace utils + +#endif + diff --git a/common/utils/string_utils.h b/common/utils/string_utils.h index 6e86b4a9..badeadca 100644 --- a/common/utils/string_utils.h +++ b/common/utils/string_utils.h @@ -1,3 +1,21 @@ +/*** + This file is part of snapcast + Copyright (C) 2014-2017 Johannes Pohl + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +***/ + #ifndef STRING_UTILS_H #define STRING_UTILS_H diff --git a/server/config.cpp b/server/config.cpp index 5ef50fb5..d146731d 100644 --- a/server/config.cpp +++ b/server/config.cpp @@ -24,32 +24,59 @@ #include #include "common/snapException.h" #include "common/strCompat.h" +#include "common/utils/file_utils.h" #include "aixlog.hpp" using namespace std; Config::Config() +{ +} + + +Config::~Config() +{ + save(); +} + + +void Config::init(const std::string& root_directory, const std::string& user, const std::string& group) { string dir; - if (getenv("HOME") == NULL) + if (!root_directory.empty()) + dir = root_directory; + else if (getenv("HOME") == NULL) dir = "/var/lib/snapserver/"; else dir = getenv("HOME"); - + if (!dir.empty() && (dir.back() != '/')) dir += "/"; if (dir.find("/var/lib/snapserver") == string::npos) dir += ".config/snapserver/"; - int status = mkdirRecursive(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + int status = utils::file::mkdirRecursive(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if ((status != 0) && (errno != EEXIST)) throw SnapException("failed to create settings directory: \"" + dir + "\": " + cpt::to_string(errno)); filename_ = dir + "server.json"; SLOG(NOTICE) << "Settings file: \"" << filename_ << "\"\n"; + if (!user.empty() && !group.empty()) + { + try + { + utils::file::do_chown(dir, user, group); + utils::file::do_chown(filename_, user, group); + } + catch(const std::exception& e) + { + LOG(ERROR) << "Exception in chown: " << e.what() << "\n"; + } + } + int fd; if ((fd = open(filename_.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { @@ -88,14 +115,10 @@ Config::Config() } -Config::~Config() -{ - save(); -} - - void Config::save() { + if (filename_.empty()) + init(); std::ofstream ofs(filename_.c_str(), std::ofstream::out|std::ofstream::trunc); json clients = { {"ConfigVersion", 2}, diff --git a/server/config.h b/server/config.h index 22c5e4fa..027a46d5 100644 --- a/server/config.h +++ b/server/config.h @@ -391,6 +391,8 @@ public: void save(); + void init(const std::string& root_directory = "", const std::string& user = "", const std::string& group = ""); + std::vector groups; private: diff --git a/server/snapServer.cpp b/server/snapServer.cpp index 13e9692c..18f2b153 100644 --- a/server/snapServer.cpp +++ b/server/snapServer.cpp @@ -162,6 +162,7 @@ int main(int argc, char* argv[]) group = user_group[1]; } + Config::instance().init("/var/lib/snapserver"); daemon.reset(new Daemon(user, group, "/var/run/snapserver/pid")); daemon->daemonize(); if (processPriority < -20) @@ -172,9 +173,12 @@ int main(int argc, char* argv[]) setpriority(PRIO_PROCESS, 0, processPriority); SLOG(NOTICE) << "daemon started" << std::endl; } + else + Config::instance().init(); +#else + Config::instance().init(); #endif - Config::instance(); #if defined(HAS_AVAHI) || defined(HAS_BONJOUR) PublishZeroConf publishZeroConfg("Snapcast");