diff options
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/util.cc | 40 | ||||
-rw-r--r-- | src/libutil/util.hh | 7 |
2 files changed, 37 insertions, 10 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc index be0a9bf317d1..5cda9a0677b5 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -413,6 +413,17 @@ void createSymlink(const Path & target, const Path & link) } +void replaceSymlink(const Path & target, const Path & link) +{ + Path tmp = canonPath(dirOf(link) + "/.new_" + baseNameOf(link)); + + createSymlink(target, tmp); + + if (rename(tmp.c_str(), link.c_str()) != 0) + throw SysError(format("renaming ‘%1%’ to ‘%2%’") % tmp % link); +} + + LogType logType = ltPretty; Verbosity verbosity = lvlInfo; @@ -931,16 +942,16 @@ string runProgram(Path program, bool searchPath, const Strings & args, checkInterrupt(); /* Create a pipe. */ - Pipe stdout, stdin; - stdout.create(); - if (!input.empty()) stdin.create(); + Pipe out, in; + out.create(); + if (!input.empty()) in.create(); /* Fork. */ Pid pid = startProcess([&]() { - if (dup2(stdout.writeSide, STDOUT_FILENO) == -1) + if (dup2(out.writeSide, STDOUT_FILENO) == -1) throw SysError("dupping stdout"); if (!input.empty()) { - if (dup2(stdin.readSide, STDIN_FILENO) == -1) + if (dup2(in.readSide, STDIN_FILENO) == -1) throw SysError("dupping stdin"); } @@ -956,16 +967,16 @@ string runProgram(Path program, bool searchPath, const Strings & args, throw SysError(format("executing ‘%1%’") % program); }); - stdout.writeSide.close(); + out.writeSide.close(); /* FIXME: This can deadlock if the input is too long. */ if (!input.empty()) { - stdin.readSide.close(); - writeFull(stdin.writeSide, input); - stdin.writeSide.close(); + in.readSide.close(); + writeFull(in.writeSide, input); + in.writeSide.close(); } - string result = drainFD(stdout.readSide); + string result = drainFD(out.readSide); /* Wait for the child to finish. */ int status = pid.wait(true); @@ -1076,6 +1087,15 @@ string chomp(const string & s) } +string trim(const string & s, const string & whitespace) +{ + auto i = s.find_first_not_of(whitespace); + if (i == string::npos) return ""; + auto j = s.find_last_not_of(whitespace); + return string(s, i, j == string::npos ? j : j - i + 1); +} + + string statusToString(int status) { if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 20330fb7699e..7d20351eec2e 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -110,6 +110,9 @@ Paths createDirs(const Path & path); /* Create a symlink. */ void createSymlink(const Path & target, const Path & link); +/* Atomically create or replace a symlink. */ +void replaceSymlink(const Path & target, const Path & link); + template<class T, class A> T singleton(const A & a) @@ -334,6 +337,10 @@ string concatStringsSep(const string & sep, const StringSet & ss); string chomp(const string & s); +/* Remove whitespace from the start and end of a string. */ +string trim(const string & s, const string & whitespace = " \n\r\t"); + + /* Convert the exit status of a child as returned by wait() into an error string. */ string statusToString(int status); |