node: report error on xattr retrieval using standard error logging

This commit is contained in:
Michael Eischer
2025-09-21 19:24:48 +02:00
parent f2b9ea6455
commit df7924f4df
17 changed files with 30 additions and 29 deletions

View File

@@ -152,11 +152,11 @@ func (f *localFile) Stat() (*ExtendedFileInfo, error) {
return f.fi, err
}
func (f *localFile) ToNode(ignoreXattrListError bool) (*restic.Node, error) {
func (f *localFile) ToNode(ignoreXattrListError bool, warnf func(format string, args ...any)) (*restic.Node, error) {
if err := f.cacheFI(); err != nil {
return nil, err
}
return nodeFromFileInfo(f.name, f.fi, ignoreXattrListError)
return nodeFromFileInfo(f.name, f.fi, ignoreXattrListError, warnf)
}
func (f *localFile) Read(p []byte) (n int, err error) {

View File

@@ -86,7 +86,7 @@ func checkMetadata(t *testing.T, f File, path string, follow bool, nodeType rest
rtest.OK(t, err)
assertFIEqual(t, fi2, fi)
node, err := f.ToNode(false)
node, err := f.ToNode(false, t.Logf)
rtest.OK(t, err)
// ModTime is likely unique per file, thus it provides a good indication that it is from the correct file

View File

@@ -333,7 +333,7 @@ func TestVSSFS(t *testing.T) {
rtest.OK(t, err)
rtest.Equals(t, "example", string(data), "unexpected file content")
node, err := f.ToNode(false)
node, err := f.ToNode(false, t.Logf)
rtest.OK(t, err)
rtest.Equals(t, node.Mode, lstatFi.Mode)

View File

@@ -267,7 +267,7 @@ func (f fakeFile) Stat() (*ExtendedFileInfo, error) {
return f.fi, nil
}
func (f fakeFile) ToNode(_ bool) (*restic.Node, error) {
func (f fakeFile) ToNode(_ bool, _ func(format string, args ...any)) (*restic.Node, error) {
node := buildBasicNode(f.name, f.fi)
// fill minimal info with current values for uid, gid

View File

@@ -48,5 +48,5 @@ type File interface {
// ToNode returns a restic.Node for the File. The internally used os.FileInfo
// must be consistent with that returned by Stat(). In particular, the metadata
// returned by consecutive calls to Stat() and ToNode() must match.
ToNode(ignoreXattrListError bool) (*restic.Node, error)
ToNode(ignoreXattrListError bool, warnf func(format string, args ...any)) (*restic.Node, error)
}

View File

@@ -15,7 +15,7 @@ import (
// nodeFromFileInfo returns a new node from the given path and FileInfo. It
// returns the first error that is encountered, together with a node.
func nodeFromFileInfo(path string, fi *ExtendedFileInfo, ignoreXattrListError bool) (*restic.Node, error) {
func nodeFromFileInfo(path string, fi *ExtendedFileInfo, ignoreXattrListError bool, warnf func(format string, args ...any)) (*restic.Node, error) {
node := buildBasicNode(path, fi)
if err := nodeFillExtendedStat(node, path, fi); err != nil {
@@ -23,7 +23,7 @@ func nodeFromFileInfo(path string, fi *ExtendedFileInfo, ignoreXattrListError bo
}
err := nodeFillGenericAttributes(node, path, fi)
err = errors.Join(err, nodeFillExtendedAttributes(node, path, ignoreXattrListError))
err = errors.Join(err, nodeFillExtendedAttributes(node, path, ignoreXattrListError, warnf))
return node, err
}

View File

@@ -13,6 +13,6 @@ func nodeRestoreExtendedAttributes(_ *restic.Node, _ string, _ func(xattrName st
}
// nodeFillExtendedAttributes is a no-op
func nodeFillExtendedAttributes(_ *restic.Node, _ string, _ bool) error {
func nodeFillExtendedAttributes(_ *restic.Node, _ string, _ bool, _ func(format string, args ...any)) error {
return nil
}

View File

@@ -31,7 +31,7 @@ func BenchmarkNodeFromFileInfo(t *testing.B) {
t.ResetTimer()
for i := 0; i < t.N; i++ {
_, err := f.ToNode(false)
_, err := f.ToNode(false, t.Logf)
rtest.OK(t, err)
}
@@ -223,9 +223,9 @@ func TestNodeRestoreAt(t *testing.T) {
fs := &Local{}
meta, err := fs.OpenFile(nodePath, O_NOFOLLOW, true)
rtest.OK(t, err)
n2, err := meta.ToNode(false)
n2, err := meta.ToNode(false, t.Logf)
rtest.OK(t, err)
n3, err := meta.ToNode(true)
n3, err := meta.ToNode(true, t.Logf)
rtest.OK(t, err)
rtest.OK(t, meta.Close())
rtest.Assert(t, n2.Equals(*n3), "unexpected node info mismatch %v", cmp.Diff(n2, n3))

View File

@@ -117,7 +117,7 @@ func TestNodeFromFileInfo(t *testing.T) {
fs := &Local{}
meta, err := fs.OpenFile(test.filename, O_NOFOLLOW, true)
rtest.OK(t, err)
node, err := meta.ToNode(false)
node, err := meta.ToNode(false, t.Logf)
rtest.OK(t, err)
rtest.OK(t, meta.Close())

View File

@@ -91,7 +91,7 @@ func nodeRestoreExtendedAttributes(node *restic.Node, path string, xattrSelectFi
// fill extended attributes in the node
// It also checks if the volume supports extended attributes and stores the result in a map
// so that it does not have to be checked again for subsequent calls for paths in the same volume.
func nodeFillExtendedAttributes(node *restic.Node, path string, _ bool) (err error) {
func nodeFillExtendedAttributes(node *restic.Node, path string, _ bool, _ func(format string, args ...any)) (err error) {
if strings.Contains(filepath.Base(path), ":") {
// Do not process for Alternate Data Streams in Windows
return nil

View File

@@ -224,7 +224,7 @@ func restoreAndGetNode(t *testing.T, tempDir string, testNode *restic.Node, warn
fs := &Local{}
meta, err := fs.OpenFile(testPath, O_NOFOLLOW, true)
test.OK(t, err)
nodeFromFileInfo, err := meta.ToNode(false)
nodeFromFileInfo, err := meta.ToNode(false, t.Logf)
test.OK(t, errors.Wrapf(err, "Could not get NodeFromFileInfo for path: %s", testPath))
test.OK(t, meta.Close())

View File

@@ -4,7 +4,6 @@
package fs
import (
"fmt"
"os"
"syscall"
@@ -97,7 +96,7 @@ func nodeRestoreExtendedAttributes(node *restic.Node, path string, xattrSelectFi
return nil
}
func nodeFillExtendedAttributes(node *restic.Node, path string, ignoreListError bool) error {
func nodeFillExtendedAttributes(node *restic.Node, path string, ignoreListError bool, warnf func(format string, args ...any)) error {
xattrs, err := listxattr(path)
debug.Log("fillExtendedAttributes(%v) %v %v", path, xattrs, err)
if err != nil {
@@ -111,7 +110,7 @@ func nodeFillExtendedAttributes(node *restic.Node, path string, ignoreListError
for _, attr := range xattrs {
attrVal, err := getxattr(path, attr)
if err != nil {
fmt.Fprintf(os.Stderr, "can not obtain extended attribute %v for %v:\n", attr, path)
warnf("can not obtain extended attribute %v for %v:\n", attr, path)
continue
}
attr := restic.ExtendedAttribute{

View File

@@ -34,7 +34,7 @@ func setAndVerifyXattr(t *testing.T, file string, attrs []restic.ExtendedAttribu
nodeActual := &restic.Node{
Type: restic.NodeTypeFile,
}
rtest.OK(t, nodeFillExtendedAttributes(nodeActual, file, false))
rtest.OK(t, nodeFillExtendedAttributes(nodeActual, file, false, t.Logf))
rtest.Assert(t, nodeActual.Equals(*node), "xattr mismatch got %v expected %v", nodeActual.ExtendedAttributes, node.ExtendedAttributes)
}
@@ -59,7 +59,7 @@ func setAndVerifyXattrWithSelectFilter(t *testing.T, file string, testAttr []tes
nodeActual := &restic.Node{
Type: restic.NodeTypeFile,
}
rtest.OK(t, nodeFillExtendedAttributes(nodeActual, file, false))
rtest.OK(t, nodeFillExtendedAttributes(nodeActual, file, false, t.Logf))
// Check nodeActual to make sure only xattrs we expect are there
for _, testAttr := range testAttr {