contents of files in the specified directory are not significant; expected
usage is to have symbolic links to the associated service description files,
but this is not required. Failure to read the directory contents, or to find
-any of the services named within, is not considered fatal.
+any of the services named within, is not considered fatal.
+
+The directory path, if not absolute, is relative to the directory containing
+the service description file.
.TP
\fBsocket\-listen\fR = \fIsocket-path\fR
Pre-open a socket for the service and pass it to the service using the
#include "cpbuffer.h"
#include "dinit-client.h"
#include "load-service.h"
+#include "dinit-util.h"
// dinitctl: utility to control the Dinit daemon, including starting and stopping of services.
return 0;
}
-// Join two paths; the 2nd must be relative
-static std::string join_paths(std::string p1, std::string p2)
-{
- std::string r = p1;
- if (*(r.rbegin()) != '/') {
- r += '/';
- }
- return r + p2;
-}
-
// exception for cancelling a service operation
class service_op_cancel { };
string service_file_path;
for (std::string path : paths) {
- string test_path = join_paths(dinit_cwd + '/' + path, from);
+ string test_path = combine_paths(dinit_cwd + '/' + path, from);
service_file.open(test_path.c_str(), ios::in);
if (service_file) {
return 1;
}
+ // The waits-for.d path is relative to the service file path, combine:
+ string waits_for_d_full = combine_paths(parent_path(service_file_path), waits_for_d.c_str());
+
// check if dependency already exists
- string dep_link_path = join_paths(waits_for_d, to);
+ string dep_link_path = combine_paths(waits_for_d_full, to);
struct stat stat_buf;
if (lstat(dep_link_path.c_str(), &stat_buf) == -1) {
if (errno != ENOENT) {
return n;
}
+// Combine two paths to produce a path. If the second path is absolute, it is returned unmodified;
+// otherwise, it is appended to the first path (with a slash separator added if needed).
+inline std::string combine_paths(const std::string &p1, const char * p2)
+{
+ if (*p2 == 0) return p1;
+ if (p1.empty()) return std::string(p2);
+
+ if (p2[0] == '/') return p2;
+
+ if (*(p1.rbegin()) == '/') return p1 + p2;
+ return p1 + '/' + p2;
+}
+
+// Find the parent path of a given path, which should refer to a named file or directory (not . or ..).
+// If the path contains no directory, returns the empty string.
+inline std::string parent_path(const std::string &p)
+{
+ auto spos = p.rfind('/');
+ if (spos == std::string::npos) {
+ return std::string {};
+ }
+
+ return p.substr(0, spos + 1);
+}
+
#endif
#include "proc-service.h"
#include "dinit-log.h"
+#include "dinit-util.h"
using string = std::string;
using string_iterator = std::string::iterator;
// a fatal error.
static void process_dep_dir(dirload_service_set &sset,
const char *servicename,
+ string service_filename,
std::list<prelim_dep> &deplist, const std::string &depdirpath,
dependency_type dep_type)
{
- DIR *depdir = opendir(depdirpath.c_str());
+ std::string depdir_fname = combine_paths(parent_path(service_filename), depdirpath.c_str());
+
+ DIR *depdir = opendir(depdir_fname.c_str());
if (depdir == nullptr) {
- log(loglevel_t::WARN, "Could not open dependency directory '", depdirpath,
+ log(loglevel_t::WARN, "Could not open dependency directory '", depdir_fname,
"' for ", servicename, " service.");
return;
}
}
ifstream service_file;
+ string service_filename;
// Couldn't find one. Have to load it.
for (auto &service_dir : service_dirs) {
- string service_filename = service_dir.get_dir();
+ service_filename = service_dir.get_dir();
if (*(service_filename.rbegin()) != '/') {
service_filename += '/';
}
}
else if (setting == "waits-for.d") {
string waitsford = read_setting_value(i, end);
- process_dep_dir(*this, name, depends, waitsford, dependency_type::WAITS_FOR);
+ process_dep_dir(*this, name, service_filename, depends, waitsford,
+ dependency_type::WAITS_FOR);
}
else if (setting == "logfile") {
logfile = read_setting_value(i, end);