forked from TrueCloudLab/rclone
local: disable xattr support if the filesystems indicates it is not supported
Before this change, if rclone was run with `-M` on a filesystem without xattr support, it would error out. This patch makes rclone detect the not supported errors and disable xattrs from then on. It prints one ERROR level message about this. See: https://forum.rclone.org/t/metadata-update-local-s3/32277/7
This commit is contained in:
parent
9f33eb2e65
commit
d347ac0154
2 changed files with 44 additions and 11 deletions
|
@ -234,15 +234,16 @@ type Options struct {
|
||||||
|
|
||||||
// Fs represents a local filesystem rooted at root
|
// Fs represents a local filesystem rooted at root
|
||||||
type Fs struct {
|
type Fs struct {
|
||||||
name string // the name of the remote
|
name string // the name of the remote
|
||||||
root string // The root directory (OS path)
|
root string // The root directory (OS path)
|
||||||
opt Options // parsed config options
|
opt Options // parsed config options
|
||||||
features *fs.Features // optional features
|
features *fs.Features // optional features
|
||||||
dev uint64 // device number of root node
|
dev uint64 // device number of root node
|
||||||
precisionOk sync.Once // Whether we need to read the precision
|
precisionOk sync.Once // Whether we need to read the precision
|
||||||
precision time.Duration // precision of local filesystem
|
precision time.Duration // precision of local filesystem
|
||||||
warnedMu sync.Mutex // used for locking access to 'warned'.
|
warnedMu sync.Mutex // used for locking access to 'warned'.
|
||||||
warned map[string]struct{} // whether we have warned about this string
|
warned map[string]struct{} // whether we have warned about this string
|
||||||
|
xattrSupported int32 // whether xattrs are supported (atomic access)
|
||||||
|
|
||||||
// do os.Lstat or os.Stat
|
// do os.Lstat or os.Stat
|
||||||
lstat func(name string) (os.FileInfo, error)
|
lstat func(name string) (os.FileInfo, error)
|
||||||
|
@ -286,6 +287,9 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
|
||||||
dev: devUnset,
|
dev: devUnset,
|
||||||
lstat: os.Lstat,
|
lstat: os.Lstat,
|
||||||
}
|
}
|
||||||
|
if xattrSupported {
|
||||||
|
f.xattrSupported = 1
|
||||||
|
}
|
||||||
f.root = cleanRootPath(root, f.opt.NoUNC, f.opt.Enc)
|
f.root = cleanRootPath(root, f.opt.NoUNC, f.opt.Enc)
|
||||||
f.features = (&fs.Features{
|
f.features = (&fs.Features{
|
||||||
CaseInsensitive: f.caseInsensitive(),
|
CaseInsensitive: f.caseInsensitive(),
|
||||||
|
|
|
@ -6,6 +6,8 @@ package local
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/pkg/xattr"
|
"github.com/pkg/xattr"
|
||||||
"github.com/rclone/rclone/fs"
|
"github.com/rclone/rclone/fs"
|
||||||
|
@ -16,12 +18,30 @@ const (
|
||||||
xattrSupported = xattr.XATTR_SUPPORTED
|
xattrSupported = xattr.XATTR_SUPPORTED
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Check to see if the error supplied is a not supported error, and if
|
||||||
|
// so, disable xattrs
|
||||||
|
func (f *Fs) xattrIsNotSupported(err error) bool {
|
||||||
|
xattrErr, ok := err.(*xattr.Error)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Xattrs not supported can be ENOTSUP or ENOATTR or EINVAL (on Solaris)
|
||||||
|
if xattrErr.Err == syscall.EINVAL || xattrErr.Err == syscall.ENOTSUP || xattrErr.Err == xattr.ENOATTR {
|
||||||
|
// Show xattrs not supported
|
||||||
|
if atomic.CompareAndSwapInt32(&f.xattrSupported, 1, 0) {
|
||||||
|
fs.Errorf(f, "xattrs not supported - disabling: %v", err)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// getXattr returns the extended attributes for an object
|
// getXattr returns the extended attributes for an object
|
||||||
//
|
//
|
||||||
// It doesn't return any attributes owned by this backend in
|
// It doesn't return any attributes owned by this backend in
|
||||||
// metadataKeys
|
// metadataKeys
|
||||||
func (o *Object) getXattr() (metadata fs.Metadata, err error) {
|
func (o *Object) getXattr() (metadata fs.Metadata, err error) {
|
||||||
if !xattrSupported {
|
if !xattrSupported || atomic.LoadInt32(&o.fs.xattrSupported) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
var list []string
|
var list []string
|
||||||
|
@ -31,6 +51,9 @@ func (o *Object) getXattr() (metadata fs.Metadata, err error) {
|
||||||
list, err = xattr.LList(o.path)
|
list, err = xattr.LList(o.path)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if o.fs.xattrIsNotSupported(err) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, fmt.Errorf("failed to read xattr: %w", err)
|
return nil, fmt.Errorf("failed to read xattr: %w", err)
|
||||||
}
|
}
|
||||||
if len(list) == 0 {
|
if len(list) == 0 {
|
||||||
|
@ -45,6 +68,9 @@ func (o *Object) getXattr() (metadata fs.Metadata, err error) {
|
||||||
v, err = xattr.LGet(o.path, k)
|
v, err = xattr.LGet(o.path, k)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if o.fs.xattrIsNotSupported(err) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return nil, fmt.Errorf("failed to read xattr key %q: %w", k, err)
|
return nil, fmt.Errorf("failed to read xattr key %q: %w", k, err)
|
||||||
}
|
}
|
||||||
k = strings.ToLower(k)
|
k = strings.ToLower(k)
|
||||||
|
@ -64,7 +90,7 @@ func (o *Object) getXattr() (metadata fs.Metadata, err error) {
|
||||||
//
|
//
|
||||||
// It doesn't set any attributes owned by this backend in metadataKeys
|
// It doesn't set any attributes owned by this backend in metadataKeys
|
||||||
func (o *Object) setXattr(metadata fs.Metadata) (err error) {
|
func (o *Object) setXattr(metadata fs.Metadata) (err error) {
|
||||||
if !xattrSupported {
|
if !xattrSupported || atomic.LoadInt32(&o.fs.xattrSupported) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for k, value := range metadata {
|
for k, value := range metadata {
|
||||||
|
@ -80,6 +106,9 @@ func (o *Object) setXattr(metadata fs.Metadata) (err error) {
|
||||||
err = xattr.LSet(o.path, k, v)
|
err = xattr.LSet(o.path, k, v)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if o.fs.xattrIsNotSupported(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return fmt.Errorf("failed to set xattr key %q: %w", k, err)
|
return fmt.Errorf("failed to set xattr key %q: %w", k, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue