X-Git-Url: https://git.hcoop.net/jackhill/guix/guix.git/blobdiff_plain/54c260e6ecc81f1836bda844ec8e661d51bfb867..d0ed201e0a9736c64cb3c59d8c987c79fd6046d6:/nix/libutil/util.cc diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index dab4235b04..17d145b4c6 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -177,8 +177,13 @@ struct stat lstat(const Path & path) bool pathExists(const Path & path) { int res; +#ifdef HAVE_STATX + struct statx st; + res = statx(AT_FDCWD, path.c_str(), AT_SYMLINK_NOFOLLOW, 0, &st); +#else struct stat st; res = lstat(path.c_str(), &st); +#endif if (!res) return true; if (errno != ENOENT && errno != ENOTDIR) throw SysError(format("getting status of %1%") % path); @@ -300,16 +305,27 @@ void writeLine(int fd, string s) } -static void _deletePath(const Path & path, unsigned long long & bytesFreed) +static void _deletePath(const Path & path, unsigned long long & bytesFreed, size_t linkThreshold) { checkInterrupt(); printMsg(lvlVomit, format("%1%") % path); +#ifdef HAVE_STATX +# define st_mode stx_mode +# define st_size stx_size +# define st_nlink stx_nlink + struct statx st; + if (statx(AT_FDCWD, path.c_str(), + AT_SYMLINK_NOFOLLOW, + STATX_SIZE | STATX_NLINK | STATX_MODE, &st) == -1) + throw SysError(format("getting status of `%1%'") % path); +#else struct stat st = lstat(path); +#endif - if (!S_ISDIR(st.st_mode) && st.st_nlink == 1) - bytesFreed += st.st_blocks * 512; + if (!S_ISDIR(st.st_mode) && st.st_nlink <= linkThreshold) + bytesFreed += st.st_size; if (S_ISDIR(st.st_mode)) { /* Make the directory writable. */ @@ -319,8 +335,11 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed) } for (auto & i : readDirectory(path)) - _deletePath(path + "/" + i.name, bytesFreed); + _deletePath(path + "/" + i.name, bytesFreed, linkThreshold); } +#undef st_mode +#undef st_size +#undef st_nlink if (remove(path.c_str()) == -1) throw SysError(format("cannot unlink `%1%'") % path); @@ -334,12 +353,12 @@ void deletePath(const Path & path) } -void deletePath(const Path & path, unsigned long long & bytesFreed) +void deletePath(const Path & path, unsigned long long & bytesFreed, size_t linkThreshold) { startNest(nest, lvlDebug, format("recursively deleting path `%1%'") % path); bytesFreed = 0; - _deletePath(path, bytesFreed); + _deletePath(path, bytesFreed, linkThreshold); } @@ -433,7 +452,7 @@ Nest::~Nest() static string escVerbosity(Verbosity level) { - return int2String((int) level); + return std::to_string((int) level); } @@ -842,6 +861,10 @@ void killUser(uid_t uid) which means "follow POSIX", which we don't want here */ if (syscall(SYS_kill, -1, SIGKILL, false) == 0) break; +#elif __GNU__ + /* Killing all a user's processes using PID=-1 does currently + not work on the Hurd. */ + if (kill(getpid(), SIGKILL) == 0) break; #else if (kill(-1, SIGKILL) == 0) break; #endif @@ -854,6 +877,10 @@ void killUser(uid_t uid) }); int status = pid.wait(true); +#if __GNU__ + /* When the child killed itself, status = SIGKILL. */ + if (status == SIGKILL) return; +#endif if (status != 0) throw Error(format("cannot kill processes for uid `%1%': %2%") % uid % statusToString(status)); @@ -897,10 +924,10 @@ pid_t startProcess(std::function fun, } -std::vector stringsToCharPtrs(const Strings & ss) +std::vector stringsToCharPtrs(const Strings & ss) { - std::vector res; - for (auto & s : ss) res.push_back(s.c_str()); + std::vector res; + for (auto & s : ss) res.push_back((char *) s.c_str()); res.push_back(0); return res; } @@ -921,12 +948,11 @@ string runProgram(Path program, bool searchPath, const Strings & args) Strings args_(args); args_.push_front(program); - auto cargs = stringsToCharPtrs(args_); if (searchPath) - execvp(program.c_str(), (char * *) &cargs[0]); + execvp(program.c_str(), stringsToCharPtrs(args_).data()); else - execv(program.c_str(), (char * *) &cargs[0]); + execv(program.c_str(), stringsToCharPtrs(args_).data()); throw SysError(format("executing `%1%'") % program); }); @@ -1107,21 +1133,6 @@ bool endOfList(std::istream & str) } -string decodeOctalEscaped(const string & s) -{ - string r; - for (string::const_iterator i = s.begin(); i != s.end(); ) { - if (*i != '\\') { r += *i++; continue; } - unsigned char c = 0; - ++i; - while (i != s.end() && *i >= '0' && *i < '8') - c = c * 8 + (*i++ - '0'); - r += c; - } - return r; -} - - void ignoreException() { try {