libstore: ignore broken symlinks in ssl-cert-file default
Also tweak `pathAccessible` to ignore other relevant errors too. It was
documented as ignoring permission errors but it was only ignoring
`EPERM`, which comes from the darwin sandbox, and not ignoring `EACCESS`
which is the real permission error. I figured it also makes sense to
ignore `ELOOP`.
Fixes: #560
Change-Id: Ibb849b68d07386eb80afb52b57f7d12b3a48a202
This commit is contained in:
parent
11950a0a79
commit
684f93e783
12
doc/manual/rl-next/ssl-cert-symlink.md
Normal file
12
doc/manual/rl-next/ssl-cert-symlink.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
synopsis: Ignore broken `/etc/ssl/certs/ca-certificates.crt` symlink
|
||||
issues: [fj#560]
|
||||
cls: [2144]
|
||||
category: Fixes
|
||||
credits: lilyball
|
||||
---
|
||||
|
||||
[`ssl-cert-file`](@docroot@/command-ref/conf-file.md#conf-ssl-cert-file) now checks its default
|
||||
value for a broken symlink before using it. This fixes a problem on macOS where uninstalling
|
||||
nix-darwin may leave behind a broken symlink at `/etc/ssl/certs/ca-certificates.crt` that was
|
||||
stopping Lix from using the cert at `/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt`.
|
|
@ -263,7 +263,7 @@ bool Settings::isWSL1()
|
|||
Path Settings::getDefaultSSLCertFile()
|
||||
{
|
||||
for (auto & fn : {"/etc/ssl/certs/ca-certificates.crt", "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
|
||||
if (pathAccessible(fn)) return fn;
|
||||
if (pathAccessible(fn, true)) return fn;
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
|
@ -214,6 +214,19 @@ struct stat lstat(const Path & path)
|
|||
return st;
|
||||
}
|
||||
|
||||
std::optional<struct stat> maybeStat(const Path & path)
|
||||
{
|
||||
std::optional<struct stat> st{std::in_place};
|
||||
if (stat(path.c_str(), &*st))
|
||||
{
|
||||
if (errno == ENOENT || errno == ENOTDIR)
|
||||
st.reset();
|
||||
else
|
||||
throw SysError("getting status of '%s'", path);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
std::optional<struct stat> maybeLstat(const Path & path)
|
||||
{
|
||||
std::optional<struct stat> st{std::in_place};
|
||||
|
@ -232,14 +245,23 @@ bool pathExists(const Path & path)
|
|||
return maybeLstat(path).has_value();
|
||||
}
|
||||
|
||||
bool pathAccessible(const Path & path)
|
||||
bool pathAccessible(const Path & path, bool resolveSymlinks)
|
||||
{
|
||||
try {
|
||||
return pathExists(path);
|
||||
return resolveSymlinks ? maybeStat(path).has_value() : pathExists(path);
|
||||
} catch (SysError & e) {
|
||||
// swallow EPERM
|
||||
if (e.errNo == EPERM) return false;
|
||||
throw;
|
||||
switch (e.errNo) {
|
||||
case EPERM:
|
||||
// operation not permitted error, can occur in darwin sandbox
|
||||
case EACCES:
|
||||
// permission error
|
||||
case ELOOP:
|
||||
// path component is a looping symlink
|
||||
// this seems like a reasonable condition to handle as well
|
||||
return false;
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,12 @@ bool isDirOrInDir(std::string_view path, std::string_view dir);
|
|||
struct stat stat(const Path & path);
|
||||
struct stat lstat(const Path & path);
|
||||
|
||||
/**
|
||||
* `stat` the given path if it exists.
|
||||
* @return std::nullopt if the path doesn't exist, or an optional containing the result of `stat` otherwise
|
||||
*/
|
||||
std::optional<struct stat> maybeStat(const Path & path);
|
||||
|
||||
/**
|
||||
* `lstat` the given path if it exists.
|
||||
* @return std::nullopt if the path doesn't exist, or an optional containing the result of `lstat` otherwise
|
||||
|
@ -137,10 +143,11 @@ bool pathExists(const Path & path);
|
|||
/**
|
||||
* A version of pathExists that returns false on a permission error.
|
||||
* Useful for inferring default paths across directories that might not
|
||||
* be readable.
|
||||
* be readable. Optionally resolves symlinks to determine if the real
|
||||
* path exists.
|
||||
* @return true iff the given path can be accessed and exists
|
||||
*/
|
||||
bool pathAccessible(const Path & path);
|
||||
bool pathAccessible(const Path & path, bool resolveSymlinks = false);
|
||||
|
||||
/**
|
||||
* Read the contents (target) of a symbolic link. The result is not
|
||||
|
|
Loading…
Reference in a new issue