fs: make generic and extended attrs independent of each other

This commit is contained in:
Michael Eischer 2024-11-02 22:45:48 +01:00
parent 6084848e5a
commit 087f95a298
6 changed files with 37 additions and 32 deletions

View file

@ -22,11 +22,8 @@ func nodeFromFileInfo(path string, fi os.FileInfo, ignoreXattrListError bool) (*
return node, err return node, err
} }
allowExtended, err := nodeFillGenericAttributes(node, path, &stat) err := nodeFillGenericAttributes(node, path, &stat)
if allowExtended {
// Skip processing ExtendedAttributes if allowExtended is false.
err = errors.Join(err, nodeFillExtendedAttributes(node, path, ignoreXattrListError)) err = errors.Join(err, nodeFillExtendedAttributes(node, path, ignoreXattrListError))
}
return node, err return node, err
} }

View file

@ -21,6 +21,6 @@ func nodeRestoreGenericAttributes(node *restic.Node, _ string, warn func(msg str
} }
// nodeFillGenericAttributes is a no-op on AIX. // nodeFillGenericAttributes is a no-op on AIX.
func nodeFillGenericAttributes(_ *restic.Node, _ string, _ *ExtendedFileInfo) (allowExtended bool, err error) { func nodeFillGenericAttributes(_ *restic.Node, _ string, _ *ExtendedFileInfo) error {
return true, nil return nil
} }

View file

@ -18,6 +18,6 @@ func nodeRestoreGenericAttributes(node *restic.Node, _ string, warn func(msg str
} }
// nodeFillGenericAttributes is a no-op on netbsd. // nodeFillGenericAttributes is a no-op on netbsd.
func nodeFillGenericAttributes(_ *restic.Node, _ string, _ *ExtendedFileInfo) (allowExtended bool, err error) { func nodeFillGenericAttributes(_ *restic.Node, _ string, _ *ExtendedFileInfo) error {
return true, nil return nil
} }

View file

@ -18,6 +18,6 @@ func nodeRestoreGenericAttributes(node *restic.Node, _ string, warn func(msg str
} }
// fillGenericAttributes is a no-op on openbsd. // fillGenericAttributes is a no-op on openbsd.
func nodeFillGenericAttributes(_ *restic.Node, _ string, _ *ExtendedFileInfo) (allowExtended bool, err error) { func nodeFillGenericAttributes(_ *restic.Node, _ string, _ *ExtendedFileInfo) error {
return true, nil return nil
} }

View file

@ -83,8 +83,28 @@ func nodeRestoreExtendedAttributes(node *restic.Node, path string) (err error) {
return nil return nil
} }
// fill extended attributes in the node. This also includes the Generic attributes for windows. // 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) (err error) {
if strings.Contains(filepath.Base(path), ":") {
// Do not process for Alternate Data Streams in Windows
return nil
}
// only capture xattrs for file/dir
if node.Type != restic.NodeTypeFile && node.Type != restic.NodeTypeDir {
return nil
}
allowExtended, err := checkAndStoreEASupport(path)
if err != nil {
return err
}
if !allowExtended {
return nil
}
var fileHandle windows.Handle var fileHandle windows.Handle
if fileHandle, err = openHandleForEA(node.Type, path, false); fileHandle == 0 { if fileHandle, err = openHandleForEA(node.Type, path, false); fileHandle == 0 {
return nil return nil
@ -316,40 +336,28 @@ func decryptFile(pathPointer *uint16) error {
// nodeFillGenericAttributes fills in the generic attributes for windows like File Attributes, // nodeFillGenericAttributes fills in the generic attributes for windows like File Attributes,
// Created time and Security Descriptors. // Created time and Security Descriptors.
// It also checks if the volume supports extended attributes and stores the result in a map func nodeFillGenericAttributes(node *restic.Node, path string, stat *ExtendedFileInfo) error {
// so that it does not have to be checked again for subsequent calls for paths in the same volume.
func nodeFillGenericAttributes(node *restic.Node, path string, stat *ExtendedFileInfo) (allowExtended bool, err error) {
if strings.Contains(filepath.Base(path), ":") { if strings.Contains(filepath.Base(path), ":") {
// Do not process for Alternate Data Streams in Windows // Do not process for Alternate Data Streams in Windows
// Also do not allow processing of extended attributes for ADS. return nil
return false, nil
} }
isVolume, err := isVolumePath(path) isVolume, err := isVolumePath(path)
if err != nil { if err != nil {
return false, err return err
} }
if isVolume { if isVolume {
// Do not process file attributes, created time and sd for windows root volume paths // Do not process file attributes, created time and sd for windows root volume paths
// Security descriptors are not supported for root volume paths. // Security descriptors are not supported for root volume paths.
// Though file attributes and created time are supported for root volume paths, // Though file attributes and created time are supported for root volume paths,
// we ignore them and we do not want to replace them during every restore. // we ignore them and we do not want to replace them during every restore.
allowExtended, err = checkAndStoreEASupport(path) return nil
if err != nil {
return false, err
}
return allowExtended, err
} }
var sd *[]byte var sd *[]byte
if node.Type == restic.NodeTypeFile || node.Type == restic.NodeTypeDir { if node.Type == restic.NodeTypeFile || node.Type == restic.NodeTypeDir {
// Check EA support and get security descriptor for file/dir only
allowExtended, err = checkAndStoreEASupport(path)
if err != nil {
return false, err
}
if sd, err = getSecurityDescriptor(path); err != nil { if sd, err = getSecurityDescriptor(path); err != nil {
return allowExtended, err return err
} }
} }
@ -361,7 +369,7 @@ func nodeFillGenericAttributes(node *restic.Node, path string, stat *ExtendedFil
FileAttributes: &winFI.FileAttributes, FileAttributes: &winFI.FileAttributes,
SecurityDescriptor: sd, SecurityDescriptor: sd,
}) })
return allowExtended, err return err
} }
// checkAndStoreEASupport checks if the volume of the path supports extended attributes and stores the result in a map // checkAndStoreEASupport checks if the volume of the path supports extended attributes and stores the result in a map

View file

@ -71,8 +71,8 @@ func nodeRestoreGenericAttributes(node *restic.Node, _ string, warn func(msg str
} }
// nodeFillGenericAttributes is a no-op. // nodeFillGenericAttributes is a no-op.
func nodeFillGenericAttributes(_ *restic.Node, _ string, _ *ExtendedFileInfo) (allowExtended bool, err error) { func nodeFillGenericAttributes(_ *restic.Node, _ string, _ *ExtendedFileInfo) error {
return true, nil return nil
} }
func nodeRestoreExtendedAttributes(node *restic.Node, path string) error { func nodeRestoreExtendedAttributes(node *restic.Node, path string) error {