Reputation: 4631
I'm trying to determine whether an os.PathError
is due to an EINVAL
or ENOENT
. How do I correctly make that determination?
res, err := os.Readlink(fpath)
if err, ok := err.(*os.PathError); ok {
if err.Err == os.ErrInvalid {
// This path here. What's the correct check?
return fpath
}
log.Printf("ResolveLinks error: %s", err)
return ""
}
log.Printf("Resolved: %s to %s", fpath, res)
return res
If fpath
points to a regular file instead of a symlink, readlink should produce EINVAL
, but my err.Err == os.ErrInvalid
check fails and the following is logged:
2019/03/28 12:04:42 ResolveLinks error: readlink foo: invalid argument
I'm supposed to unpack the PathError, but then what? Compare the error string?
I notice that the os module has certain functions to match error types, like os.IsNotExist
, but I don't see one for all possible error codes.
Upvotes: 2
Views: 1183
Reputation: 4631
I've found that the error's string will allow to match on the error type, but I'm not confident (at all) this works across platforms or even locales.
if err, ok := err.(*os.PathError); ok {
//EINVAL
if err.Err.Error() == "invalid argument" {
…
// - OR -
//ENOENT
if err.Err.Error() == "no such file or directory" {
…
}
Upvotes: 0
Reputation: 10136
The err.Err
is of type syscall.Errno
and this is integer type that you can convert to int. Running this code on Ubuntu produces error code 22:
if serr, ok := err.Err.(syscall.Errno); ok {
fmt.Println(int(serr))
}
Bear in mind I do not know if this kind of check is cross platform or not.
if you just want to check file is symlink you can use Lstat to get FileInfo
struct and do the check:
fi.Mode() & os.ModeSymlink != 0
Upvotes: 1