diff --git a/internal/fs/node_windows.go b/internal/fs/node_windows.go index 0a9064fc5..9d46143cc 100644 --- a/internal/fs/node_windows.go +++ b/internal/fs/node_windows.go @@ -5,7 +5,6 @@ import ( "fmt" "path/filepath" "reflect" - "runtime" "strings" "sync" "syscall" @@ -17,17 +16,6 @@ import ( "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 ( modAdvapi32 = syscall.NewLazyDLL("advapi32.dll") 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. -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() unknownAttribs, err = restic.GenericAttributesToOSAttrs(attrs, reflect.TypeOf(windowsAttributes), &waValue, "windows") return windowsAttributes, unknownAttribs, err @@ -365,7 +353,7 @@ func nodeFillGenericAttributes(node *restic.Node, path string, stat *ExtendedFil winFI := stat.Sys().(*syscall.Win32FileAttributeData) // Add Windows attributes - node.GenericAttributes, err = WindowsAttrsToGenericAttributes(WindowsAttributes{ + node.GenericAttributes, err = restic.WindowsAttrsToGenericAttributes(restic.WindowsAttributes{ CreationTime: &winFI.CreationTime, FileAttributes: &winFI.FileAttributes, SecurityDescriptor: sd, @@ -462,10 +450,3 @@ func prepareVolumeName(path string) (volumeName string, err error) { } 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) -} diff --git a/internal/fs/node_windows_test.go b/internal/fs/node_windows_test.go index 218e729ce..83ad72d53 100644 --- a/internal/fs/node_windows_test.go +++ b/internal/fs/node_windows_test.go @@ -36,7 +36,7 @@ func testRestoreSecurityDescriptor(t *testing.T, sd string, tempDir string, file sdInputBytes, err := base64.StdEncoding.DecodeString(sd) 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. - 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)) // Construct a Node with the generic attributes. 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) 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) @@ -83,7 +83,7 @@ func TestRestoreCreationTime(t *testing.T) { attr := fi.Sys().(*syscall.Win32FileAttributeData) creationTimeAttribute := attr.CreationTime //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) { @@ -95,7 +95,7 @@ func TestRestoreFileAttributes(t *testing.T) { system := uint32(syscall.FILE_ATTRIBUTE_SYSTEM) archive := uint32(syscall.FILE_ATTRIBUTE_ARCHIVE) encrypted := uint32(windows.FILE_ATTRIBUTE_ENCRYPTED) - fileAttributes := []WindowsAttributes{ + fileAttributes := []restic.WindowsAttributes{ //normal {FileAttributes: &normal}, //hidden @@ -108,7 +108,7 @@ func TestRestoreFileAttributes(t *testing.T) { {FileAttributes: &encrypted}, } for i, fileAttr := range fileAttributes { - genericAttrs, err := WindowsAttrsToGenericAttributes(fileAttr) + genericAttrs, err := restic.WindowsAttrsToGenericAttributes(fileAttr) test.OK(t, err) expectedNodes := []restic.Node{ { @@ -128,7 +128,7 @@ func TestRestoreFileAttributes(t *testing.T) { system = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_SYSTEM) archive = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_ARCHIVE) encrypted = uint32(syscall.FILE_ATTRIBUTE_DIRECTORY | windows.FILE_ATTRIBUTE_ENCRYPTED) - folderAttributes := []WindowsAttributes{ + folderAttributes := []restic.WindowsAttributes{ //normal {FileAttributes: &normal}, //hidden @@ -141,7 +141,7 @@ func TestRestoreFileAttributes(t *testing.T) { {FileAttributes: &encrypted}, } for i, folderAttr := range folderAttributes { - genericAttrs, err := WindowsAttrsToGenericAttributes(folderAttr) + genericAttrs, err := restic.WindowsAttrsToGenericAttributes(folderAttr) test.OK(t, err) 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) { - genericAttributes, err := WindowsAttrsToGenericAttributes(genericAttributeExpected) +func runGenericAttributesTest(t *testing.T, tempDir string, genericAttributeName restic.GenericAttributeType, genericAttributeExpected restic.WindowsAttributes, warningExpected bool) { + genericAttributes, err := restic.WindowsAttrsToGenericAttributes(genericAttributeExpected) test.OK(t, err) expectedNodes := []restic.Node{ { @@ -183,12 +183,12 @@ func runGenericAttributesTest(t *testing.T, tempDir string, genericAttributeName } 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 { testPath, node := restoreAndGetNode(t, tempDir, &testNode, warningExpected) rawMessage := node.GenericAttributes[genericAttr] - genericAttrsExpected, err := WindowsAttrsToGenericAttributes(genericAttributeExpected) + genericAttrsExpected, err := restic.WindowsAttrsToGenericAttributes(genericAttributeExpected) test.OK(t, err) rawMessageExpected := genericAttrsExpected[genericAttr] test.Equals(t, rawMessageExpected, rawMessage, "Generic attribute: %s got from NodeFromFileInfo not equal for path: %s", string(genericAttr), testPath) diff --git a/internal/restic/node_windows.go b/internal/restic/node_windows.go new file mode 100644 index 000000000..7df426665 --- /dev/null +++ b/internal/restic/node_windows.go @@ -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) +} diff --git a/internal/restorer/restorer_windows_test.go b/internal/restorer/restorer_windows_test.go index 9fcdfc48d..4764bed2d 100644 --- a/internal/restorer/restorer_windows_test.go +++ b/internal/restorer/restorer_windows_test.go @@ -16,7 +16,6 @@ import ( "unsafe" "github.com/restic/restic/internal/errors" - "github.com/restic/restic/internal/fs" "github.com/restic/restic/internal/repository" "github.com/restic/restic/internal/restic" "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 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) return attrs }