fs: move WindowsAttributes definition back to restic package

This commit is contained in:
Michael Eischer 2024-08-27 16:00:29 +02:00
parent ebdd946ac1
commit e2bce1b9ee
4 changed files with 40 additions and 34 deletions

View file

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"reflect" "reflect"
"runtime"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
@ -17,17 +16,6 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
// WindowsAttributes are the genericAttributes for Windows OS
type WindowsAttributes struct {
// CreationTime is used for storing creation time for windows files.
CreationTime *syscall.Filetime `generic:"creation_time"`
// FileAttributes is used for storing file attributes for windows files.
FileAttributes *uint32 `generic:"file_attributes"`
// SecurityDescriptor is used for storing security descriptors which includes
// owner, group, discretionary access control list (DACL), system access control list (SACL)
SecurityDescriptor *[]byte `generic:"security_descriptor"`
}
var ( var (
modAdvapi32 = syscall.NewLazyDLL("advapi32.dll") modAdvapi32 = syscall.NewLazyDLL("advapi32.dll")
procEncryptFile = modAdvapi32.NewProc("EncryptFileW") procEncryptFile = modAdvapi32.NewProc("EncryptFileW")
@ -205,7 +193,7 @@ func nodeRestoreGenericAttributes(node *restic.Node, path string, warn func(msg
} }
// genericAttributesToWindowsAttrs converts the generic attributes map to a WindowsAttributes and also returns a string of unknown attributes that it could not convert. // genericAttributesToWindowsAttrs converts the generic attributes map to a WindowsAttributes and also returns a string of unknown attributes that it could not convert.
func genericAttributesToWindowsAttrs(attrs map[restic.GenericAttributeType]json.RawMessage) (windowsAttributes WindowsAttributes, unknownAttribs []restic.GenericAttributeType, err error) { func genericAttributesToWindowsAttrs(attrs map[restic.GenericAttributeType]json.RawMessage) (windowsAttributes restic.WindowsAttributes, unknownAttribs []restic.GenericAttributeType, err error) {
waValue := reflect.ValueOf(&windowsAttributes).Elem() waValue := reflect.ValueOf(&windowsAttributes).Elem()
unknownAttribs, err = restic.GenericAttributesToOSAttrs(attrs, reflect.TypeOf(windowsAttributes), &waValue, "windows") unknownAttribs, err = restic.GenericAttributesToOSAttrs(attrs, reflect.TypeOf(windowsAttributes), &waValue, "windows")
return windowsAttributes, unknownAttribs, err return windowsAttributes, unknownAttribs, err
@ -365,7 +353,7 @@ func nodeFillGenericAttributes(node *restic.Node, path string, stat *ExtendedFil
winFI := stat.Sys().(*syscall.Win32FileAttributeData) winFI := stat.Sys().(*syscall.Win32FileAttributeData)
// Add Windows attributes // Add Windows attributes
node.GenericAttributes, err = WindowsAttrsToGenericAttributes(WindowsAttributes{ node.GenericAttributes, err = restic.WindowsAttrsToGenericAttributes(restic.WindowsAttributes{
CreationTime: &winFI.CreationTime, CreationTime: &winFI.CreationTime,
FileAttributes: &winFI.FileAttributes, FileAttributes: &winFI.FileAttributes,
SecurityDescriptor: sd, SecurityDescriptor: sd,
@ -462,10 +450,3 @@ func prepareVolumeName(path string) (volumeName string, err error) {
} }
return volumeName, nil return volumeName, nil
} }
// windowsAttrsToGenericAttributes converts the WindowsAttributes to a generic attributes map using reflection
func WindowsAttrsToGenericAttributes(windowsAttributes WindowsAttributes) (attrs map[restic.GenericAttributeType]json.RawMessage, err error) {
// Get the value of the WindowsAttributes
windowsAttributesValue := reflect.ValueOf(windowsAttributes)
return restic.OSAttrsToGenericAttributes(reflect.TypeOf(windowsAttributes), &windowsAttributesValue, runtime.GOOS)
}

View file

@ -36,7 +36,7 @@ func testRestoreSecurityDescriptor(t *testing.T, sd string, tempDir string, file
sdInputBytes, err := base64.StdEncoding.DecodeString(sd) sdInputBytes, err := base64.StdEncoding.DecodeString(sd)
test.OK(t, errors.Wrapf(err, "Error decoding SD for: %s", fileName)) test.OK(t, errors.Wrapf(err, "Error decoding SD for: %s", fileName))
// Wrap the security descriptor bytes in windows attributes and convert to generic attributes. // Wrap the security descriptor bytes in windows attributes and convert to generic attributes.
genericAttributes, err := WindowsAttrsToGenericAttributes(WindowsAttributes{CreationTime: nil, FileAttributes: nil, SecurityDescriptor: &sdInputBytes}) genericAttributes, err := restic.WindowsAttrsToGenericAttributes(restic.WindowsAttributes{CreationTime: nil, FileAttributes: nil, SecurityDescriptor: &sdInputBytes})
test.OK(t, errors.Wrapf(err, "Error constructing windows attributes for: %s", fileName)) test.OK(t, errors.Wrapf(err, "Error constructing windows attributes for: %s", fileName))
// Construct a Node with the generic attributes. // Construct a Node with the generic attributes.
expectedNode := getNode(fileName, fileType, genericAttributes) expectedNode := getNode(fileName, fileType, genericAttributes)
@ -68,7 +68,7 @@ func getNode(name string, fileType restic.NodeType, genericAttributes map[restic
} }
} }
func getWindowsAttr(t *testing.T, testPath string, node *restic.Node) WindowsAttributes { func getWindowsAttr(t *testing.T, testPath string, node *restic.Node) restic.WindowsAttributes {
windowsAttributes, unknownAttribs, err := genericAttributesToWindowsAttrs(node.GenericAttributes) windowsAttributes, unknownAttribs, err := genericAttributesToWindowsAttrs(node.GenericAttributes)
test.OK(t, errors.Wrapf(err, "Error getting windows attr from generic attr: %s", testPath)) test.OK(t, errors.Wrapf(err, "Error getting windows attr from generic attr: %s", testPath))
test.Assert(t, len(unknownAttribs) == 0, "Unknown attribs found: %s for: %s", unknownAttribs, testPath) test.Assert(t, len(unknownAttribs) == 0, "Unknown attribs found: %s for: %s", unknownAttribs, testPath)
@ -83,7 +83,7 @@ func TestRestoreCreationTime(t *testing.T) {
attr := fi.Sys().(*syscall.Win32FileAttributeData) attr := fi.Sys().(*syscall.Win32FileAttributeData)
creationTimeAttribute := attr.CreationTime creationTimeAttribute := attr.CreationTime
//Using the temp dir creation time as the test creation time for the test file and folder //Using the temp dir creation time as the test creation time for the test file and folder
runGenericAttributesTest(t, path, restic.TypeCreationTime, WindowsAttributes{CreationTime: &creationTimeAttribute}, false) runGenericAttributesTest(t, path, restic.TypeCreationTime, restic.WindowsAttributes{CreationTime: &creationTimeAttribute}, false)
} }
func TestRestoreFileAttributes(t *testing.T) { func TestRestoreFileAttributes(t *testing.T) {
@ -95,7 +95,7 @@ func TestRestoreFileAttributes(t *testing.T) {
system := uint32(syscall.FILE_ATTRIBUTE_SYSTEM) system := uint32(syscall.FILE_ATTRIBUTE_SYSTEM)
archive := uint32(syscall.FILE_ATTRIBUTE_ARCHIVE) archive := uint32(syscall.FILE_ATTRIBUTE_ARCHIVE)
encrypted := uint32(windows.FILE_ATTRIBUTE_ENCRYPTED) encrypted := uint32(windows.FILE_ATTRIBUTE_ENCRYPTED)
fileAttributes := []WindowsAttributes{ fileAttributes := []restic.WindowsAttributes{
//normal //normal
{FileAttributes: &normal}, {FileAttributes: &normal},
//hidden //hidden
@ -108,7 +108,7 @@ func TestRestoreFileAttributes(t *testing.T) {
{FileAttributes: &encrypted}, {FileAttributes: &encrypted},
} }
for i, fileAttr := range fileAttributes { for i, fileAttr := range fileAttributes {
genericAttrs, err := WindowsAttrsToGenericAttributes(fileAttr) genericAttrs, err := restic.WindowsAttrsToGenericAttributes(fileAttr)
test.OK(t, err) test.OK(t, err)
expectedNodes := []restic.Node{ expectedNodes := []restic.Node{
{ {
@ -128,7 +128,7 @@ func TestRestoreFileAttributes(t *testing.T) {
system = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_SYSTEM) system = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_SYSTEM)
archive = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_ARCHIVE) archive = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_ARCHIVE)
encrypted = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_ENCRYPTED) encrypted = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_ENCRYPTED)
folderAttributes := []WindowsAttributes{ folderAttributes := []restic.WindowsAttributes{
//normal //normal
{FileAttributes: &normal}, {FileAttributes: &normal},
//hidden //hidden
@ -141,7 +141,7 @@ func TestRestoreFileAttributes(t *testing.T) {
{FileAttributes: &encrypted}, {FileAttributes: &encrypted},
} }
for i, folderAttr := range folderAttributes { for i, folderAttr := range folderAttributes {
genericAttrs, err := WindowsAttrsToGenericAttributes(folderAttr) genericAttrs, err := restic.WindowsAttrsToGenericAttributes(folderAttr)
test.OK(t, err) test.OK(t, err)
expectedNodes := []restic.Node{ expectedNodes := []restic.Node{
{ {
@ -158,8 +158,8 @@ func TestRestoreFileAttributes(t *testing.T) {
} }
} }
func runGenericAttributesTest(t *testing.T, tempDir string, genericAttributeName restic.GenericAttributeType, genericAttributeExpected WindowsAttributes, warningExpected bool) { func runGenericAttributesTest(t *testing.T, tempDir string, genericAttributeName restic.GenericAttributeType, genericAttributeExpected restic.WindowsAttributes, warningExpected bool) {
genericAttributes, err := WindowsAttrsToGenericAttributes(genericAttributeExpected) genericAttributes, err := restic.WindowsAttrsToGenericAttributes(genericAttributeExpected)
test.OK(t, err) test.OK(t, err)
expectedNodes := []restic.Node{ expectedNodes := []restic.Node{
{ {
@ -183,12 +183,12 @@ func runGenericAttributesTest(t *testing.T, tempDir string, genericAttributeName
} }
runGenericAttributesTestForNodes(t, expectedNodes, tempDir, genericAttributeName, genericAttributeExpected, warningExpected) runGenericAttributesTestForNodes(t, expectedNodes, tempDir, genericAttributeName, genericAttributeExpected, warningExpected)
} }
func runGenericAttributesTestForNodes(t *testing.T, expectedNodes []restic.Node, tempDir string, genericAttr restic.GenericAttributeType, genericAttributeExpected WindowsAttributes, warningExpected bool) { func runGenericAttributesTestForNodes(t *testing.T, expectedNodes []restic.Node, tempDir string, genericAttr restic.GenericAttributeType, genericAttributeExpected restic.WindowsAttributes, warningExpected bool) {
for _, testNode := range expectedNodes { for _, testNode := range expectedNodes {
testPath, node := restoreAndGetNode(t, tempDir, &testNode, warningExpected) testPath, node := restoreAndGetNode(t, tempDir, &testNode, warningExpected)
rawMessage := node.GenericAttributes[genericAttr] rawMessage := node.GenericAttributes[genericAttr]
genericAttrsExpected, err := WindowsAttrsToGenericAttributes(genericAttributeExpected) genericAttrsExpected, err := restic.WindowsAttrsToGenericAttributes(genericAttributeExpected)
test.OK(t, err) test.OK(t, err)
rawMessageExpected := genericAttrsExpected[genericAttr] rawMessageExpected := genericAttrsExpected[genericAttr]
test.Equals(t, rawMessageExpected, rawMessage, "Generic attribute: %s got from NodeFromFileInfo not equal for path: %s", string(genericAttr), testPath) test.Equals(t, rawMessageExpected, rawMessage, "Generic attribute: %s got from NodeFromFileInfo not equal for path: %s", string(genericAttr), testPath)

View file

@ -0,0 +1,26 @@
package restic
import (
"encoding/json"
"reflect"
"runtime"
"syscall"
)
// WindowsAttributes are the genericAttributes for Windows OS
type WindowsAttributes struct {
// CreationTime is used for storing creation time for windows files.
CreationTime *syscall.Filetime `generic:"creation_time"`
// FileAttributes is used for storing file attributes for windows files.
FileAttributes *uint32 `generic:"file_attributes"`
// SecurityDescriptor is used for storing security descriptors which includes
// owner, group, discretionary access control list (DACL), system access control list (SACL)
SecurityDescriptor *[]byte `generic:"security_descriptor"`
}
// windowsAttrsToGenericAttributes converts the WindowsAttributes to a generic attributes map using reflection
func WindowsAttrsToGenericAttributes(windowsAttributes WindowsAttributes) (attrs map[GenericAttributeType]json.RawMessage, err error) {
// Get the value of the WindowsAttributes
windowsAttributesValue := reflect.ValueOf(windowsAttributes)
return OSAttrsToGenericAttributes(reflect.TypeOf(windowsAttributes), &windowsAttributesValue, runtime.GOOS)
}

View file

@ -16,7 +16,6 @@ import (
"unsafe" "unsafe"
"github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/fs"
"github.com/restic/restic/internal/repository" "github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/test" "github.com/restic/restic/internal/test"
@ -264,7 +263,7 @@ func setup(t *testing.T, nodesMap map[string]Node) *Restorer {
//If the node is a directory add FILE_ATTRIBUTE_DIRECTORY to attributes //If the node is a directory add FILE_ATTRIBUTE_DIRECTORY to attributes
fileattr |= windows.FILE_ATTRIBUTE_DIRECTORY fileattr |= windows.FILE_ATTRIBUTE_DIRECTORY
} }
attrs, err := fs.WindowsAttrsToGenericAttributes(fs.WindowsAttributes{FileAttributes: &fileattr}) attrs, err := restic.WindowsAttrsToGenericAttributes(restic.WindowsAttributes{FileAttributes: &fileattr})
test.OK(t, err) test.OK(t, err)
return attrs return attrs
} }