mirror of
https://github.com/lxc/incus.git
synced 2026-02-06 12:46:34 +01:00
When parsing extended attributes, we may be getting EINVAL when run on ZFS. This appears to be when dealing with ZFS namespaced xattrs and despite being real root with all capabilities, there appears to be no way to read or even clear those attributes. So instead of crashing mid-shift, let's just log them and move on. Signed-off-by: Stéphane Graber <stgraber@stgraber.org> Sponsored-by: https://webdock.io
71 lines
1.8 KiB
Go
71 lines
1.8 KiB
Go
//go:build linux && cgo
|
|
|
|
package idmap
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/pkg/xattr"
|
|
"golang.org/x/sys/unix"
|
|
|
|
"github.com/lxc/incus/v6/shared/logger"
|
|
)
|
|
|
|
// The functions below are verbatim copies of the functions found in the internal package.
|
|
// They have been copied here due to there not being a good place for
|
|
// them in the shared package and because we have a policy not to import
|
|
// anything from internal in one of our shared packages.
|
|
|
|
// getAllXattr retrieves all extended attributes associated with a file, directory or symbolic link.
|
|
func getAllXattr(path string) (map[string]string, error) {
|
|
xattrNames, err := xattr.LList(path)
|
|
if err != nil {
|
|
// Some filesystems don't support llistxattr() for various reasons.
|
|
// Interpret this as a set of no xattrs, instead of an error.
|
|
if errors.Is(err, unix.EOPNOTSUPP) {
|
|
return nil, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("Failed getting extended attributes from %q: %w", path, err)
|
|
}
|
|
|
|
xattrs := make(map[string]string, len(xattrNames))
|
|
for _, xattrName := range xattrNames {
|
|
value, err := xattr.LGet(path, xattrName)
|
|
if err != nil {
|
|
if errors.Is(err, unix.EINVAL) {
|
|
logger.Warn("Skipping unreadable xattr during shift", logger.Ctx{"path": path, "xattr": xattrName})
|
|
continue
|
|
}
|
|
|
|
return nil, fmt.Errorf("Failed getting %q extended attribute from %q: %w", xattrName, path, err)
|
|
}
|
|
|
|
xattrs[xattrName] = string(value)
|
|
}
|
|
|
|
return xattrs, nil
|
|
}
|
|
|
|
// getErrno checks if the Go error is a kernel errno.
|
|
func getErrno(err error) (iserrno bool, errno error) {
|
|
sysErr, ok := err.(*os.SyscallError)
|
|
if ok {
|
|
return true, sysErr.Err
|
|
}
|
|
|
|
pathErr, ok := err.(*os.PathError)
|
|
if ok {
|
|
return true, pathErr.Err
|
|
}
|
|
|
|
tmpErrno, ok := err.(unix.Errno)
|
|
if ok {
|
|
return true, tmpErrno
|
|
}
|
|
|
|
return false, nil
|
|
}
|