Fix symlink resolution on Linux and FreeBSD.
Linux's open returns ENOTDIR when used with O_DIRECTORY|O_NOFOLLOW and the path is a symlink. Update the code to expect this. FreeBSD's open returns EMLINK instead of ELOOP when using O_NOFOLLOW on symlink. Update the code to expect this.
This commit is contained in:
@@ -737,6 +737,23 @@ pub fn path_open(
|
|||||||
return wasm32::__WASI_ENXIO;
|
return wasm32::__WASI_ENXIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Linux returns ENOTDIR instead of ELOOP when using O_NOFOLLOW|O_DIRECTORY
|
||||||
|
// on a symlink.
|
||||||
|
Some(Errno::ENOTDIR)
|
||||||
|
if !(nix_all_oflags & (OFlag::O_NOFOLLOW | OFlag::O_DIRECTORY)).is_empty() =>
|
||||||
|
{
|
||||||
|
if let Ok(stat) = fstatat(dir, path.as_os_str(), AtFlags::AT_SYMLINK_NOFOLLOW) {
|
||||||
|
if SFlag::from_bits_truncate(stat.st_mode).contains(SFlag::S_IFLNK) {
|
||||||
|
return wasm32::__WASI_ELOOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wasm32::__WASI_ENOTDIR;
|
||||||
|
}
|
||||||
|
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
|
||||||
|
// a symlink.
|
||||||
|
Some(Errno::EMLINK) if !(nix_all_oflags & OFlag::O_NOFOLLOW).is_empty() => {
|
||||||
|
return wasm32::__WASI_ELOOP;
|
||||||
|
}
|
||||||
Some(e) => return wasm32::errno_from_nix(e),
|
Some(e) => return wasm32::errno_from_nix(e),
|
||||||
None => return wasm32::__WASI_ENOSYS,
|
None => return wasm32::__WASI_ENOSYS,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,8 +158,11 @@ pub fn path_get<P: AsRef<OsStr>>(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Err(e)
|
Err(e)
|
||||||
|
// Check to see if it was a symlink. Linux indicates
|
||||||
|
// this with ENOTDIR because of the O_DIRECTORY flag.
|
||||||
if e.as_errno() == Some(Errno::ELOOP)
|
if e.as_errno() == Some(Errno::ELOOP)
|
||||||
|| e.as_errno() == Some(Errno::EMLINK) =>
|
|| e.as_errno() == Some(Errno::EMLINK)
|
||||||
|
|| e.as_errno() == Some(Errno::ENOTDIR) =>
|
||||||
{
|
{
|
||||||
// attempt symlink expansion
|
// attempt symlink expansion
|
||||||
match readlinkat(
|
match readlinkat(
|
||||||
|
|||||||
Reference in New Issue
Block a user