From 6d3a5260d358cd89e8727fd279a94dd8d553ff35 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 21 Jul 2024 16:00:47 +0200 Subject: [PATCH] fs: unexport a several windows functions --- internal/fs/ea_windows.go | 36 ++++++++++----------- internal/fs/ea_windows_test.go | 32 +++++++++---------- internal/fs/file_unix.go | 4 +-- internal/fs/file_windows.go | 16 +++++----- internal/fs/fs_local_vss.go | 4 +-- internal/fs/fs_local_vss_test.go | 7 ++-- internal/fs/node.go | 2 +- internal/fs/node_windows.go | 36 ++++++++++----------- internal/fs/node_windows_test.go | 18 +++++------ internal/fs/sd_windows.go | 44 +++++++++++++------------- internal/fs/sd_windows_test.go | 10 +++--- internal/fs/sd_windows_test_helpers.go | 18 +++++------ internal/fs/vss.go | 4 +-- internal/fs/vss_windows.go | 5 +-- 14 files changed, 119 insertions(+), 117 deletions(-) diff --git a/internal/fs/ea_windows.go b/internal/fs/ea_windows.go index bf7b02fd4..6bfe20209 100644 --- a/internal/fs/ea_windows.go +++ b/internal/fs/ea_windows.go @@ -56,14 +56,14 @@ var ( errEaValueTooLarge = errors.New("extended attribute value too large") ) -// ExtendedAttribute represents a single Windows EA. -type ExtendedAttribute struct { +// extendedAttribute represents a single Windows EA. +type extendedAttribute struct { Name string Value []byte Flags uint8 } -func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { +func parseEa(b []byte) (ea extendedAttribute, nb []byte, err error) { var info fileFullEaInformation err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info) if err != nil { @@ -90,9 +90,9 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { return ea, nb, err } -// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION +// decodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION // buffer retrieved from BackupRead, ZwQueryEaFile, etc. -func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) { +func decodeExtendedAttributes(b []byte) (eas []extendedAttribute, err error) { for len(b) != 0 { ea, nb, err := parseEa(b) if err != nil { @@ -105,7 +105,7 @@ func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) { return eas, err } -func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { +func writeEa(buf *bytes.Buffer, ea *extendedAttribute, last bool) error { if int(uint8(len(ea.Name))) != len(ea.Name) { return errEaNameTooLarge } @@ -153,9 +153,9 @@ func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { return nil } -// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION +// encodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION // buffer for use with BackupWrite, ZwSetEaFile, etc. -func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) { +func encodeExtendedAttributes(eas []extendedAttribute) ([]byte, error) { var buf bytes.Buffer for i := range eas { last := false @@ -217,11 +217,11 @@ const ( STATUS_NO_EAS_ON_FILE = -1073741742 ) -// GetFileEA retrieves the extended attributes for the file represented by `handle`. The +// fgetEA retrieves the extended attributes for the file represented by `handle`. The // `handle` must have been opened with file access flag FILE_READ_EA (0x8). // The extended file attribute names in windows are case-insensitive and when fetching // the attributes the names are generally returned in UPPER case. -func GetFileEA(handle windows.Handle) ([]ExtendedAttribute, error) { +func fgetEA(handle windows.Handle) ([]extendedAttribute, error) { // default buffer size to start with bufLen := 1024 buf := make([]byte, bufLen) @@ -246,13 +246,13 @@ func GetFileEA(handle windows.Handle) ([]ExtendedAttribute, error) { } break } - return DecodeExtendedAttributes(buf) + return decodeExtendedAttributes(buf) } -// SetFileEA sets the extended attributes for the file represented by `handle`. The +// fsetEA sets the extended attributes for the file represented by `handle`. The // handle must have been opened with the file access flag FILE_WRITE_EA(0x10). -func SetFileEA(handle windows.Handle, attrs []ExtendedAttribute) error { - encodedEA, err := EncodeExtendedAttributes(attrs) +func fsetEA(handle windows.Handle, attrs []extendedAttribute) error { + encodedEA, err := encodeExtendedAttributes(attrs) if err != nil { return fmt.Errorf("failed to encoded extended attributes: %w", err) } @@ -285,8 +285,8 @@ func setFileEA(handle windows.Handle, iosb *ioStatusBlock, buf *uint8, bufLen ui return } -// PathSupportsExtendedAttributes returns true if the path supports extended attributes. -func PathSupportsExtendedAttributes(path string) (supported bool, err error) { +// pathSupportsExtendedAttributes returns true if the path supports extended attributes. +func pathSupportsExtendedAttributes(path string) (supported bool, err error) { var fileSystemFlags uint32 utf16Path, err := windows.UTF16PtrFromString(path) if err != nil { @@ -300,8 +300,8 @@ func PathSupportsExtendedAttributes(path string) (supported bool, err error) { return supported, nil } -// GetVolumePathName returns the volume path name for the given path. -func GetVolumePathName(path string) (volumeName string, err error) { +// getVolumePathName returns the volume path name for the given path. +func getVolumePathName(path string) (volumeName string, err error) { utf16Path, err := windows.UTF16PtrFromString(path) if err != nil { return "", err diff --git a/internal/fs/ea_windows_test.go b/internal/fs/ea_windows_test.go index e474a3735..64bc7f7b6 100644 --- a/internal/fs/ea_windows_test.go +++ b/internal/fs/ea_windows_test.go @@ -46,7 +46,7 @@ import ( // under MIT license. var ( - testEas = []ExtendedAttribute{ + testEas = []extendedAttribute{ {Name: "foo", Value: []byte("bar")}, {Name: "fizz", Value: []byte("buzz")}, } @@ -58,14 +58,14 @@ var ( ) func TestRoundTripEas(t *testing.T) { - b, err := EncodeExtendedAttributes(testEas) + b, err := encodeExtendedAttributes(testEas) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(testEasEncoded, b) { t.Fatalf("Encoded mismatch %v %v", testEasEncoded, b) } - eas, err := DecodeExtendedAttributes(b) + eas, err := decodeExtendedAttributes(b) if err != nil { t.Fatal(err) } @@ -75,7 +75,7 @@ func TestRoundTripEas(t *testing.T) { } func TestEasDontNeedPaddingAtEnd(t *testing.T) { - eas, err := DecodeExtendedAttributes(testEasNotPadded) + eas, err := decodeExtendedAttributes(testEasNotPadded) if err != nil { t.Fatal(err) } @@ -85,21 +85,21 @@ func TestEasDontNeedPaddingAtEnd(t *testing.T) { } func TestTruncatedEasFailCorrectly(t *testing.T) { - _, err := DecodeExtendedAttributes(testEasTruncated) + _, err := decodeExtendedAttributes(testEasTruncated) if err == nil { t.Fatal("expected error") } } func TestNilEasEncodeAndDecodeAsNil(t *testing.T) { - b, err := EncodeExtendedAttributes(nil) + b, err := encodeExtendedAttributes(nil) if err != nil { t.Fatal(err) } if len(b) != 0 { t.Fatal("expected empty") } - eas, err := DecodeExtendedAttributes(nil) + eas, err := decodeExtendedAttributes(nil) if err != nil { t.Fatal(err) } @@ -178,8 +178,8 @@ func setupTestFolder(t *testing.T) string { return testfolderPath } -func generateTestEAs(t *testing.T, nAttrs int, path string) []ExtendedAttribute { - testEAs := make([]ExtendedAttribute, nAttrs) +func generateTestEAs(t *testing.T, nAttrs int, path string) []extendedAttribute { + testEAs := make([]extendedAttribute, nAttrs) for i := 0; i < nAttrs; i++ { testEAs[i].Name = fmt.Sprintf("TESTEA%d", i+1) testEAs[i].Value = make([]byte, getRandomInt()) @@ -231,12 +231,12 @@ func cleanupTestFile(t *testing.T, path string) { } } -func testSetGetEA(t *testing.T, path string, handle windows.Handle, testEAs []ExtendedAttribute) { - if err := SetFileEA(handle, testEAs); err != nil { +func testSetGetEA(t *testing.T, path string, handle windows.Handle, testEAs []extendedAttribute) { + if err := fsetEA(handle, testEAs); err != nil { t.Fatalf("set EA for path %s failed: %s", path, err) } - readEAs, err := GetFileEA(handle) + readEAs, err := fgetEA(handle) if err != nil { t.Fatalf("get EA for path %s failed: %s", path, err) } @@ -262,7 +262,7 @@ func TestPathSupportsExtendedAttributes(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - supported, err := PathSupportsExtendedAttributes(tc.path) + supported, err := pathSupportsExtendedAttributes(tc.path) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -273,7 +273,7 @@ func TestPathSupportsExtendedAttributes(t *testing.T) { } // Test with an invalid path - _, err := PathSupportsExtendedAttributes("Z:\\NonExistentPath-UAS664da5s4dyu56das45f5as") + _, err := pathSupportsExtendedAttributes("Z:\\NonExistentPath-UAS664da5s4dyu56das45f5as") if err == nil { t.Error("Expected an error for non-existent path, but got nil") } @@ -305,7 +305,7 @@ func TestGetVolumePathName(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - volumeName, err := GetVolumePathName(tc.path) + volumeName, err := getVolumePathName(tc.path) if err != nil { t.Fatalf("Unexpected error: %v", err) } @@ -316,7 +316,7 @@ func TestGetVolumePathName(t *testing.T) { } // Test with an invalid path - _, err := GetVolumePathName("Z:\\NonExistentPath") + _, err := getVolumePathName("Z:\\NonExistentPath") if err == nil { t.Error("Expected an error for non-existent path, but got nil") } diff --git a/internal/fs/file_unix.go b/internal/fs/file_unix.go index b562d15b1..4e7765c30 100644 --- a/internal/fs/file_unix.go +++ b/internal/fs/file_unix.go @@ -37,8 +37,8 @@ func isNotSupported(err error) bool { return false } -// Chmod changes the mode of the named file to mode. -func Chmod(name string, mode os.FileMode) error { +// chmod changes the mode of the named file to mode. +func chmod(name string, mode os.FileMode) error { err := os.Chmod(fixpath(name), mode) // ignore the error if the FS does not support setting this mode (e.g. CIFS with gvfs on Linux) diff --git a/internal/fs/file_windows.go b/internal/fs/file_windows.go index 7a6d79f25..3d011f719 100644 --- a/internal/fs/file_windows.go +++ b/internal/fs/file_windows.go @@ -75,17 +75,17 @@ func TempFile(dir, prefix string) (f *os.File, err error) { } // Chmod changes the mode of the named file to mode. -func Chmod(name string, mode os.FileMode) error { +func chmod(name string, mode os.FileMode) error { return os.Chmod(fixpath(name), mode) } -// ClearSystem removes the system attribute from the file. -func ClearSystem(path string) error { - return ClearAttribute(path, windows.FILE_ATTRIBUTE_SYSTEM) +// clearSystem removes the system attribute from the file. +func clearSystem(path string) error { + return clearAttribute(path, windows.FILE_ATTRIBUTE_SYSTEM) } -// ClearAttribute removes the specified attribute from the file. -func ClearAttribute(path string, attribute uint32) error { +// clearAttribute removes the specified attribute from the file. +func clearAttribute(path string, attribute uint32) error { ptr, err := windows.UTF16PtrFromString(fixpath(path)) if err != nil { return err @@ -105,8 +105,8 @@ func ClearAttribute(path string, attribute uint32) error { return nil } -// OpenHandleForEA return a file handle for file or dir for setting/getting EAs -func OpenHandleForEA(nodeType restic.NodeType, path string, writeAccess bool) (handle windows.Handle, err error) { +// openHandleForEA return a file handle for file or dir for setting/getting EAs +func openHandleForEA(nodeType restic.NodeType, path string, writeAccess bool) (handle windows.Handle, err error) { path = fixpath(path) fileAccess := windows.FILE_READ_EA if writeAccess { diff --git a/internal/fs/fs_local_vss.go b/internal/fs/fs_local_vss.go index 46b40d013..27abcf9ea 100644 --- a/internal/fs/fs_local_vss.go +++ b/internal/fs/fs_local_vss.go @@ -79,7 +79,7 @@ func parseMountPoints(list string, msgError ErrorHandler) (volumes map[string]st return } for _, s := range strings.Split(list, ";") { - if v, err := GetVolumeNameForVolumeMountPoint(s); err != nil { + if v, err := getVolumeNameForVolumeMountPoint(s); err != nil { msgError(s, errors.Errorf("failed to parse vss.exclude-volumes [%s]: %s", s, err)) } else { if volumes == nil { @@ -146,7 +146,7 @@ func (fs *LocalVss) isMountPointIncluded(mountPoint string) bool { return true } - volume, err := GetVolumeNameForVolumeMountPoint(mountPoint) + volume, err := getVolumeNameForVolumeMountPoint(mountPoint) if err != nil { fs.msgError(mountPoint, errors.Errorf("failed to get volume from mount point [%s]: %s", mountPoint, err)) return true diff --git a/internal/fs/fs_local_vss_test.go b/internal/fs/fs_local_vss_test.go index 60262c873..a59882381 100644 --- a/internal/fs/fs_local_vss_test.go +++ b/internal/fs/fs_local_vss_test.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package fs @@ -120,10 +121,10 @@ func TestVSSConfig(t *testing.T) { func TestParseMountPoints(t *testing.T) { volumeMatch := regexp.MustCompile(`^\\\\\?\\Volume\{[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}\}\\$`) - // It's not a good idea to test functions based on GetVolumeNameForVolumeMountPoint by calling - // GetVolumeNameForVolumeMountPoint itself, but we have restricted test environment: + // It's not a good idea to test functions based on getVolumeNameForVolumeMountPoint by calling + // getVolumeNameForVolumeMountPoint itself, but we have restricted test environment: // cannot manage volumes and can only be sure that the mount point C:\ exists - sysVolume, err := GetVolumeNameForVolumeMountPoint("C:") + sysVolume, err := getVolumeNameForVolumeMountPoint("C:") if err != nil { t.Fatal(err) } diff --git a/internal/fs/node.go b/internal/fs/node.go index 3945c426e..2dfe54172 100644 --- a/internal/fs/node.go +++ b/internal/fs/node.go @@ -306,7 +306,7 @@ func nodeRestoreMetadata(node *restic.Node, path string, warn func(msg string)) // calling Chmod below will no longer allow any modifications to be made on the file and the // calls above would fail. if node.Type != restic.NodeTypeSymlink { - if err := Chmod(path, node.Mode); err != nil { + if err := chmod(path, node.Mode); err != nil { if firsterr == nil { firsterr = errors.WithStack(err) } diff --git a/internal/fs/node_windows.go b/internal/fs/node_windows.go index d904c37fe..d529e3503 100644 --- a/internal/fs/node_windows.go +++ b/internal/fs/node_windows.go @@ -85,9 +85,9 @@ func nodeRestoreSymlinkTimestamps(path string, utimes [2]syscall.Timespec) error func nodeRestoreExtendedAttributes(node *restic.Node, path string) (err error) { count := len(node.ExtendedAttributes) if count > 0 { - eas := make([]ExtendedAttribute, count) + eas := make([]extendedAttribute, count) for i, attr := range node.ExtendedAttributes { - eas[i] = ExtendedAttribute{Name: attr.Name, Value: attr.Value} + eas[i] = extendedAttribute{Name: attr.Name, Value: attr.Value} } if errExt := restoreExtendedAttributes(node.Type, path, eas); errExt != nil { return errExt @@ -99,7 +99,7 @@ func nodeRestoreExtendedAttributes(node *restic.Node, path string) (err error) { // fill extended attributes in the node. This also includes the Generic attributes for windows. func nodeFillExtendedAttributes(node *restic.Node, path string, _ bool) (err error) { 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 } if err != nil { @@ -107,8 +107,8 @@ func nodeFillExtendedAttributes(node *restic.Node, path string, _ bool) (err err } defer closeFileHandle(fileHandle, path) // Replaced inline defer with named function call //Get the windows Extended Attributes using the file handle - var extAtts []ExtendedAttribute - extAtts, err = GetFileEA(fileHandle) + var extAtts []extendedAttribute + extAtts, err = fgetEA(fileHandle) debug.Log("fillExtendedAttributes(%v) %v", path, extAtts) if err != nil { return errors.Errorf("get EA failed for path %v, with: %v", path, err) @@ -139,9 +139,9 @@ func closeFileHandle(fileHandle windows.Handle, path string) { // restoreExtendedAttributes handles restore of the Windows Extended Attributes to the specified path. // The Windows API requires setting of all the Extended Attributes in one call. -func restoreExtendedAttributes(nodeType restic.NodeType, path string, eas []ExtendedAttribute) (err error) { +func restoreExtendedAttributes(nodeType restic.NodeType, path string, eas []extendedAttribute) (err error) { var fileHandle windows.Handle - if fileHandle, err = OpenHandleForEA(nodeType, path, true); fileHandle == 0 { + if fileHandle, err = openHandleForEA(nodeType, path, true); fileHandle == 0 { return nil } if err != nil { @@ -150,7 +150,7 @@ func restoreExtendedAttributes(nodeType restic.NodeType, path string, eas []Exte defer closeFileHandle(fileHandle, path) // Replaced inline defer with named function call // clear old unexpected xattrs by setting them to an empty value - oldEAs, err := GetFileEA(fileHandle) + oldEAs, err := fgetEA(fileHandle) if err != nil { return err } @@ -165,11 +165,11 @@ func restoreExtendedAttributes(nodeType restic.NodeType, path string, eas []Exte } if !found { - eas = append(eas, ExtendedAttribute{Name: oldEA.Name, Value: nil}) + eas = append(eas, extendedAttribute{Name: oldEA.Name, Value: nil}) } } - if err = SetFileEA(fileHandle, eas); err != nil { + if err = fsetEA(fileHandle, eas); err != nil { return errors.Errorf("set EA failed for path %v, with: %v", path, err) } return nil @@ -230,7 +230,7 @@ func nodeRestoreGenericAttributes(node *restic.Node, path string, warn func(msg } } if windowsAttributes.SecurityDescriptor != nil { - if err := SetSecurityDescriptor(path, windowsAttributes.SecurityDescriptor); err != nil { + if err := setSecurityDescriptor(path, windowsAttributes.SecurityDescriptor); err != nil { errs = append(errs, fmt.Errorf("error restoring security descriptor for: %s : %v", path, err)) } } @@ -296,7 +296,7 @@ func fixEncryptionAttribute(path string, attrs *uint32, pathPointer *uint16) (er if err != nil { return fmt.Errorf("failed to encrypt file: failed to reset permissions: %s : %v", path, err) } - err = ClearSystem(path) + err = clearSystem(path) if err != nil { return fmt.Errorf("failed to encrypt file: failed to clear system flag: %s : %v", path, err) } @@ -324,7 +324,7 @@ func fixEncryptionAttribute(path string, attrs *uint32, pathPointer *uint16) (er if err != nil { return fmt.Errorf("failed to encrypt file: failed to reset permissions: %s : %v", path, err) } - err = ClearSystem(path) + err = clearSystem(path) if err != nil { return fmt.Errorf("failed to decrypt file: failed to clear system flag: %s : %v", path, err) } @@ -392,7 +392,7 @@ func nodeFillGenericAttributes(node *restic.Node, path string, fi os.FileInfo, s if err != nil { return false, err } - if sd, err = GetSecurityDescriptor(path); err != nil { + if sd, err = getSecurityDescriptor(path); err != nil { return allowExtended, err } } @@ -422,7 +422,7 @@ func checkAndStoreEASupport(path string) (isEASupportedVolume bool, err error) { return eaSupportedValue.(bool), nil } // If not found, check if EA is supported with manually prepared volume name - isEASupportedVolume, err = PathSupportsExtendedAttributes(volumeName + `\`) + isEASupportedVolume, err = pathSupportsExtendedAttributes(volumeName + `\`) // If the prepared volume name is not valid, we will fetch the actual volume name next. if err != nil && !errors.Is(err, windows.DNS_ERROR_INVALID_NAME) { debug.Log("Error checking if extended attributes are supported for prepared volume name %s: %v", volumeName, err) @@ -431,8 +431,8 @@ func checkAndStoreEASupport(path string) (isEASupportedVolume bool, err error) { return false, nil } } - // If an entry is not found, get the actual volume name using the GetVolumePathName function - volumeNameActual, err := GetVolumePathName(path) + // If an entry is not found, get the actual volume name + volumeNameActual, err := getVolumePathName(path) if err != nil { debug.Log("Error getting actual volume name %s for path %s: %v", volumeName, path, err) // There can be multiple errors like path does not exist, bad network path, etc. @@ -447,7 +447,7 @@ func checkAndStoreEASupport(path string) (isEASupportedVolume bool, err error) { return eaSupportedValue.(bool), nil } // If the actual volume name is different and is not in the map, again check if the new volume supports extended attributes with the actual volume name - isEASupportedVolume, err = PathSupportsExtendedAttributes(volumeNameActual + `\`) + isEASupportedVolume, err = pathSupportsExtendedAttributes(volumeNameActual + `\`) // Debug log for cases where the prepared volume name is not valid if err != nil { debug.Log("Error checking if extended attributes are supported for actual volume name %s: %v", volumeNameActual, err) diff --git a/internal/fs/node_windows_test.go b/internal/fs/node_windows_test.go index 729ce2adb..618364879 100644 --- a/internal/fs/node_windows_test.go +++ b/internal/fs/node_windows_test.go @@ -23,10 +23,10 @@ import ( func TestRestoreSecurityDescriptors(t *testing.T) { t.Parallel() tempDir := t.TempDir() - for i, sd := range TestFileSDs { + for i, sd := range testFileSDs { testRestoreSecurityDescriptor(t, sd, tempDir, restic.NodeTypeFile, fmt.Sprintf("testfile%d", i)) } - for i, sd := range TestDirSDs { + for i, sd := range testDirSDs { testRestoreSecurityDescriptor(t, sd, tempDir, restic.NodeTypeDir, fmt.Sprintf("testdir%d", i)) } } @@ -47,13 +47,13 @@ func testRestoreSecurityDescriptor(t *testing.T, sd string, tempDir string, file sdByteFromRestoredNode := getWindowsAttr(t, testPath, node).SecurityDescriptor // Get the security descriptor for the test path after the restore. - sdBytesFromRestoredPath, err := GetSecurityDescriptor(testPath) + sdBytesFromRestoredPath, err := getSecurityDescriptor(testPath) test.OK(t, errors.Wrapf(err, "Error while getting the security descriptor for: %s", testPath)) // Compare the input SD and the SD got from the restored file. - CompareSecurityDescriptors(t, testPath, sdInputBytes, *sdBytesFromRestoredPath) + compareSecurityDescriptors(t, testPath, sdInputBytes, *sdBytesFromRestoredPath) // Compare the SD got from node constructed from the restored file info and the SD got directly from the restored file. - CompareSecurityDescriptors(t, testPath, *sdByteFromRestoredNode, *sdBytesFromRestoredPath) + compareSecurityDescriptors(t, testPath, *sdByteFromRestoredNode, *sdBytesFromRestoredPath) } func getNode(name string, fileType restic.NodeType, genericAttributes map[restic.GenericAttributeType]json.RawMessage) restic.Node { @@ -312,12 +312,12 @@ func TestRestoreExtendedAttributes(t *testing.T) { test.OK(t, errors.Wrapf(err, "Error closing file for: %s", testPath)) }() - extAttr, err := GetFileEA(handle) + extAttr, err := fgetEA(handle) test.OK(t, errors.Wrapf(err, "Error getting extended attributes for: %s", testPath)) test.Equals(t, len(node.ExtendedAttributes), len(extAttr)) for _, expectedExtAttr := range node.ExtendedAttributes { - var foundExtAttr *ExtendedAttribute + var foundExtAttr *extendedAttribute for _, ea := range extAttr { if strings.EqualFold(ea.Name, expectedExtAttr.Name) { foundExtAttr = &ea @@ -491,13 +491,13 @@ func TestPrepareVolumeName(t *testing.T) { test.Equals(t, tc.expectedVolume, volume) if tc.isRealPath { - isEASupportedVolume, err := PathSupportsExtendedAttributes(volume + `\`) + isEASupportedVolume, err := pathSupportsExtendedAttributes(volume + `\`) // If the prepared volume name is not valid, we will next fetch the actual volume name. test.OK(t, err) test.Equals(t, tc.expectedEASupported, isEASupportedVolume) - actualVolume, err := GetVolumePathName(tc.path) + actualVolume, err := getVolumePathName(tc.path) test.OK(t, err) test.Equals(t, tc.expectedVolume, actualVolume) } diff --git a/internal/fs/sd_windows.go b/internal/fs/sd_windows.go index 0004f1809..c68926f24 100644 --- a/internal/fs/sd_windows.go +++ b/internal/fs/sd_windows.go @@ -19,14 +19,14 @@ var ( onceBackup sync.Once onceRestore sync.Once - // SeBackupPrivilege allows the application to bypass file and directory ACLs to back up files and directories. - SeBackupPrivilege = "SeBackupPrivilege" - // SeRestorePrivilege allows the application to bypass file and directory ACLs to restore files and directories. - SeRestorePrivilege = "SeRestorePrivilege" - // SeSecurityPrivilege allows read and write access to all SACLs. - SeSecurityPrivilege = "SeSecurityPrivilege" - // SeTakeOwnershipPrivilege allows the application to take ownership of files and directories, regardless of the permissions set on them. - SeTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege" + // seBackupPrivilege allows the application to bypass file and directory ACLs to back up files and directories. + seBackupPrivilege = "SeBackupPrivilege" + // seRestorePrivilege allows the application to bypass file and directory ACLs to restore files and directories. + seRestorePrivilege = "SeRestorePrivilege" + // seSecurityPrivilege allows read and write access to all SACLs. + seSecurityPrivilege = "SeSecurityPrivilege" + // seTakeOwnershipPrivilege allows the application to take ownership of files and directories, regardless of the permissions set on them. + seTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege" lowerPrivileges atomic.Bool ) @@ -40,10 +40,10 @@ var lowBackupSecurityFlags windows.SECURITY_INFORMATION = windows.OWNER_SECURITY // Flags for restore without admin permissions. If there are no admin permissions, only the DACL from the SD can be restored and owner and group will be set based on the current user. var lowRestoreSecurityFlags windows.SECURITY_INFORMATION = windows.DACL_SECURITY_INFORMATION | windows.ATTRIBUTE_SECURITY_INFORMATION | windows.PROTECTED_DACL_SECURITY_INFORMATION -// GetSecurityDescriptor takes the path of the file and returns the SecurityDescriptor for the file. +// getSecurityDescriptor takes the path of the file and returns the SecurityDescriptor for the file. // This needs admin permissions or SeBackupPrivilege for getting the full SD. // If there are no admin permissions, only the current user's owner, group and DACL will be got. -func GetSecurityDescriptor(filePath string) (securityDescriptor *[]byte, err error) { +func getSecurityDescriptor(filePath string) (securityDescriptor *[]byte, err error) { onceBackup.Do(enableBackupPrivilege) var sd *windows.SECURITY_DESCRIPTOR @@ -59,7 +59,7 @@ func GetSecurityDescriptor(filePath string) (securityDescriptor *[]byte, err err if !useLowerPrivileges && isHandlePrivilegeNotHeldError(err) { // If ERROR_PRIVILEGE_NOT_HELD is encountered, fallback to backups/restores using lower non-admin privileges. lowerPrivileges.Store(true) - return GetSecurityDescriptor(filePath) + return getSecurityDescriptor(filePath) } else if errors.Is(err, windows.ERROR_NOT_SUPPORTED) { return nil, nil } else { @@ -74,15 +74,15 @@ func GetSecurityDescriptor(filePath string) (securityDescriptor *[]byte, err err return &sdBytes, nil } -// SetSecurityDescriptor sets the SecurityDescriptor for the file at the specified path. +// setSecurityDescriptor sets the SecurityDescriptor for the file at the specified path. // This needs admin permissions or SeRestorePrivilege, SeSecurityPrivilege and SeTakeOwnershipPrivilege // for setting the full SD. // If there are no admin permissions/required privileges, only the DACL from the SD can be set and // owner and group will be set based on the current user. -func SetSecurityDescriptor(filePath string, securityDescriptor *[]byte) error { +func setSecurityDescriptor(filePath string, securityDescriptor *[]byte) error { onceRestore.Do(enableRestorePrivilege) // Set the security descriptor on the file - sd, err := SecurityDescriptorBytesToStruct(*securityDescriptor) + sd, err := securityDescriptorBytesToStruct(*securityDescriptor) if err != nil { return fmt.Errorf("error converting bytes to security descriptor: %w", err) } @@ -120,7 +120,7 @@ func SetSecurityDescriptor(filePath string, securityDescriptor *[]byte) error { if !useLowerPrivileges && isHandlePrivilegeNotHeldError(err) { // If ERROR_PRIVILEGE_NOT_HELD is encountered, fallback to backups/restores using lower non-admin privileges. lowerPrivileges.Store(true) - return SetSecurityDescriptor(filePath, securityDescriptor) + return setSecurityDescriptor(filePath, securityDescriptor) } else { return fmt.Errorf("set named security info failed with: %w", err) } @@ -150,7 +150,7 @@ func setNamedSecurityInfoLow(filePath string, dacl *windows.ACL) error { // enableBackupPrivilege enables privilege for backing up security descriptors func enableBackupPrivilege() { - err := enableProcessPrivileges([]string{SeBackupPrivilege}) + err := enableProcessPrivileges([]string{seBackupPrivilege}) if err != nil { debug.Log("error enabling backup privilege: %v", err) } @@ -158,7 +158,7 @@ func enableBackupPrivilege() { // enableBackupPrivilege enables privilege for restoring security descriptors func enableRestorePrivilege() { - err := enableProcessPrivileges([]string{SeRestorePrivilege, SeSecurityPrivilege, SeTakeOwnershipPrivilege}) + err := enableProcessPrivileges([]string{seRestorePrivilege, seSecurityPrivilege, seTakeOwnershipPrivilege}) if err != nil { debug.Log("error enabling restore/security privilege: %v", err) } @@ -174,9 +174,9 @@ func isHandlePrivilegeNotHeldError(err error) bool { return false } -// SecurityDescriptorBytesToStruct converts the security descriptor bytes representation +// securityDescriptorBytesToStruct converts the security descriptor bytes representation // into a pointer to windows SECURITY_DESCRIPTOR. -func SecurityDescriptorBytesToStruct(sd []byte) (*windows.SECURITY_DESCRIPTOR, error) { +func securityDescriptorBytesToStruct(sd []byte) (*windows.SECURITY_DESCRIPTOR, error) { if l := int(unsafe.Sizeof(windows.SECURITY_DESCRIPTOR{})); len(sd) < l { return nil, fmt.Errorf("securityDescriptor (%d) smaller than expected (%d): %w", len(sd), l, windows.ERROR_INCORRECT_SIZE) } @@ -245,13 +245,13 @@ var ( privNameMutex sync.Mutex ) -// PrivilegeError represents an error enabling privileges. -type PrivilegeError struct { +// privilegeError represents an error enabling privileges. +type privilegeError struct { privileges []uint64 } // Error returns the string message for the error. -func (e *PrivilegeError) Error() string { +func (e *privilegeError) Error() string { s := "Could not enable privilege " if len(e.privileges) > 1 { s = "Could not enable privileges " diff --git a/internal/fs/sd_windows_test.go b/internal/fs/sd_windows_test.go index e78241ed3..c31b19b8b 100644 --- a/internal/fs/sd_windows_test.go +++ b/internal/fs/sd_windows_test.go @@ -28,7 +28,7 @@ func TestSetGetFileSecurityDescriptors(t *testing.T) { } }() - testSecurityDescriptors(t, TestFileSDs, testfilePath) + testSecurityDescriptors(t, testFileSDs, testfilePath) } func TestSetGetFolderSecurityDescriptors(t *testing.T) { @@ -40,7 +40,7 @@ func TestSetGetFolderSecurityDescriptors(t *testing.T) { t.Fatalf("failed to create temporary file: %s", err) } - testSecurityDescriptors(t, TestDirSDs, testfolderPath) + testSecurityDescriptors(t, testDirSDs, testfolderPath) } func testSecurityDescriptors(t *testing.T, testSDs []string, testPath string) { @@ -48,13 +48,13 @@ func testSecurityDescriptors(t *testing.T, testSDs []string, testPath string) { sdInputBytes, err := base64.StdEncoding.DecodeString(testSD) test.OK(t, errors.Wrapf(err, "Error decoding SD: %s", testPath)) - err = SetSecurityDescriptor(testPath, &sdInputBytes) + err = setSecurityDescriptor(testPath, &sdInputBytes) test.OK(t, errors.Wrapf(err, "Error setting file security descriptor for: %s", testPath)) var sdOutputBytes *[]byte - sdOutputBytes, err = GetSecurityDescriptor(testPath) + sdOutputBytes, err = getSecurityDescriptor(testPath) test.OK(t, errors.Wrapf(err, "Error getting file security descriptor for: %s", testPath)) - CompareSecurityDescriptors(t, testPath, sdInputBytes, *sdOutputBytes) + compareSecurityDescriptors(t, testPath, sdInputBytes, *sdOutputBytes) } } diff --git a/internal/fs/sd_windows_test_helpers.go b/internal/fs/sd_windows_test_helpers.go index 8b3be5fd7..0e888884a 100644 --- a/internal/fs/sd_windows_test_helpers.go +++ b/internal/fs/sd_windows_test_helpers.go @@ -13,18 +13,18 @@ import ( ) var ( - TestFileSDs = []string{"AQAUvBQAAAAwAAAAAAAAAEwAAAABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvqAwAAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSarAQIAAAIAfAAEAAAAAAAkAKkAEgABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvtAwAAABAUAP8BHwABAQAAAAAABRIAAAAAEBgA/wEfAAECAAAAAAAFIAAAACACAAAAECQA/wEfAAEFAAAAAAAFFQAAAIifWK5WoILqzL0mq+oDAAA=", + testFileSDs = []string{"AQAUvBQAAAAwAAAAAAAAAEwAAAABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvqAwAAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSarAQIAAAIAfAAEAAAAAAAkAKkAEgABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvtAwAAABAUAP8BHwABAQAAAAAABRIAAAAAEBgA/wEfAAECAAAAAAAFIAAAACACAAAAECQA/wEfAAEFAAAAAAAFFQAAAIifWK5WoILqzL0mq+oDAAA=", "AQAUvBQAAAAwAAAAAAAAAEwAAAABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvqAwAAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSarAQIAAAIAyAAHAAAAAAAUAKkAEgABAQAAAAAABQcAAAAAABQAiQASAAEBAAAAAAAFBwAAAAAAJACpABIAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSar7QMAAAAAJAC/ARMAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSar6gMAAAAAFAD/AR8AAQEAAAAAAAUSAAAAAAAYAP8BHwABAgAAAAAABSAAAAAgAgAAAAAkAP8BHwABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvqAwAA", "AQAUvBQAAAAwAAAA7AAAAEwAAAABBQAAAAAABRUAAAAvr7t03PyHGk2FokNHCAAAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSarAQIAAAIAoAAFAAAAAAAkAP8BHwABBQAAAAAABRUAAAAvr7t03PyHGk2FokNHCAAAAAAkAKkAEgABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvtAwAAABAUAP8BHwABAQAAAAAABRIAAAAAEBgA/wEfAAECAAAAAAAFIAAAACACAAAAECQA/wEfAAEFAAAAAAAFFQAAAIifWK5WoILqzL0mq+oDAAACAHQAAwAAAAKAJAC/AQIAAQUAAAAAAAUVAAAAL6+7dNz8hxpNhaJDtgQAAALAJAC/AQMAAQUAAAAAAAUVAAAAL6+7dNz8hxpNhaJDPgkAAAJAJAD/AQ8AAQUAAAAAAAUVAAAAL6+7dNz8hxpNhaJDtQQAAA==", } - TestDirSDs = []string{"AQAUvBQAAAAwAAAAAAAAAEwAAAABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvqAwAAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSarAQIAAAIAfAAEAAAAAAAkAKkAEgABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvtAwAAABMUAP8BHwABAQAAAAAABRIAAAAAExgA/wEfAAECAAAAAAAFIAAAACACAAAAEyQA/wEfAAEFAAAAAAAFFQAAAIifWK5WoILqzL0mq+oDAAA=", + testDirSDs = []string{"AQAUvBQAAAAwAAAAAAAAAEwAAAABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvqAwAAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSarAQIAAAIAfAAEAAAAAAAkAKkAEgABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvtAwAAABMUAP8BHwABAQAAAAAABRIAAAAAExgA/wEfAAECAAAAAAAFIAAAACACAAAAEyQA/wEfAAEFAAAAAAAFFQAAAIifWK5WoILqzL0mq+oDAAA=", "AQAUvBQAAAAwAAAAAAAAAEwAAAABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvqAwAAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSarAQIAAAIA3AAIAAAAAAIUAKkAEgABAQAAAAAABQcAAAAAAxQAiQASAAEBAAAAAAAFBwAAAAAAJACpABIAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSar7QMAAAAAJAC/ARMAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSar6gMAAAALFAC/ARMAAQEAAAAAAAMAAAAAABMUAP8BHwABAQAAAAAABRIAAAAAExgA/wEfAAECAAAAAAAFIAAAACACAAAAEyQA/wEfAAEFAAAAAAAFFQAAAIifWK5WoILqzL0mq+oDAAA=", "AQAUvBQAAAAwAAAA7AAAAEwAAAABBQAAAAAABRUAAAAvr7t03PyHGk2FokNHCAAAAQUAAAAAAAUVAAAAiJ9YrlaggurMvSarAQIAAAIAoAAFAAAAAAAkAP8BHwABBQAAAAAABRUAAAAvr7t03PyHGk2FokNHCAAAAAAkAKkAEgABBQAAAAAABRUAAACIn1iuVqCC6sy9JqvtAwAAABMUAP8BHwABAQAAAAAABRIAAAAAExgA/wEfAAECAAAAAAAFIAAAACACAAAAEyQA/wEfAAEFAAAAAAAFFQAAAIifWK5WoILqzL0mq+oDAAACAHQAAwAAAAKAJAC/AQIAAQUAAAAAAAUVAAAAL6+7dNz8hxpNhaJDtgQAAALAJAC/AQMAAQUAAAAAAAUVAAAAL6+7dNz8hxpNhaJDPgkAAAJAJAD/AQ8AAQUAAAAAAAUVAAAAL6+7dNz8hxpNhaJDtQQAAA==", } ) -// IsAdmin checks if current user is an administrator. -func IsAdmin() (isAdmin bool, err error) { +// isAdmin checks if current user is an administrator. +func isAdmin() (isAdmin bool, err error) { var sid *windows.SID err = windows.AllocateAndInitializeSid(&windows.SECURITY_NT_AUTHORITY, 2, windows.SECURITY_BUILTIN_DOMAIN_RID, windows.DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid) @@ -40,15 +40,15 @@ func IsAdmin() (isAdmin bool, err error) { return member, nil } -// CompareSecurityDescriptors runs tests for comparing 2 security descriptors in []byte format. -func CompareSecurityDescriptors(t *testing.T, testPath string, sdInputBytes, sdOutputBytes []byte) { - sdInput, err := SecurityDescriptorBytesToStruct(sdInputBytes) +// compareSecurityDescriptors runs tests for comparing 2 security descriptors in []byte format. +func compareSecurityDescriptors(t *testing.T, testPath string, sdInputBytes, sdOutputBytes []byte) { + sdInput, err := securityDescriptorBytesToStruct(sdInputBytes) test.OK(t, errors.Wrapf(err, "Error converting SD to struct for: %s", testPath)) - sdOutput, err := SecurityDescriptorBytesToStruct(sdOutputBytes) + sdOutput, err := securityDescriptorBytesToStruct(sdOutputBytes) test.OK(t, errors.Wrapf(err, "Error converting SD to struct for: %s", testPath)) - isAdmin, err := IsAdmin() + isAdmin, err := isAdmin() test.OK(t, errors.Wrapf(err, "Error checking if user is admin: %s", testPath)) var ownerExpected *windows.SID diff --git a/internal/fs/vss.go b/internal/fs/vss.go index 8bfffab71..3215c9aa3 100644 --- a/internal/fs/vss.go +++ b/internal/fs/vss.go @@ -33,9 +33,9 @@ func HasSufficientPrivilegesForVSS() error { return errors.New("VSS snapshots are only supported on windows") } -// GetVolumeNameForVolumeMountPoint add trailing backslash to input parameter +// getVolumeNameForVolumeMountPoint add trailing backslash to input parameter // and calls the equivalent windows api. -func GetVolumeNameForVolumeMountPoint(mountPoint string) (string, error) { +func getVolumeNameForVolumeMountPoint(mountPoint string) (string, error) { return mountPoint, nil } diff --git a/internal/fs/vss_windows.go b/internal/fs/vss_windows.go index 0b51b00f3..bb168c553 100644 --- a/internal/fs/vss_windows.go +++ b/internal/fs/vss_windows.go @@ -22,6 +22,7 @@ import ( type HRESULT uint // HRESULT constant values necessary for using VSS api. +// //nolint:golint const ( S_OK HRESULT = 0x00000000 @@ -830,9 +831,9 @@ func HasSufficientPrivilegesForVSS() error { return err } -// GetVolumeNameForVolumeMountPoint add trailing backslash to input parameter +// getVolumeNameForVolumeMountPoint add trailing backslash to input parameter // and calls the equivalent windows api. -func GetVolumeNameForVolumeMountPoint(mountPoint string) (string, error) { +func getVolumeNameForVolumeMountPoint(mountPoint string) (string, error) { if mountPoint != "" && mountPoint[len(mountPoint)-1] != filepath.Separator { mountPoint += string(filepath.Separator) }