mirror of
https://github.com/restic/restic.git
synced 2025-12-11 18:47:50 +00:00
node: report error on xattr retrieval using standard error logging
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user