1
0
Fork 0
mirror of https://github.com/restic/restic.git synced 2025-01-18 13:31:08 +00:00

fs: implement file reopening

This commit is contained in:
Michael Eischer 2024-11-16 21:27:21 +01:00
parent c0d727dfed
commit f1ae5a21e2
3 changed files with 68 additions and 0 deletions

View file

@ -23,3 +23,9 @@ func openMetadataHandle(path string, flag int) (*os.File, error) {
_ = setFlags(f)
return f, nil
}
// reopenMetadataHandle reopens a handle created by openMetadataHandle for reading.
// The caller must no longer use the original file.
func reopenMetadataHandle(f *os.File) (*os.File, error) {
return f, nil
}

View file

@ -2,6 +2,7 @@ package fs
import (
"os"
"syscall"
"golang.org/x/sys/unix"
)
@ -23,3 +24,30 @@ func openMetadataHandle(path string, flag int) (*os.File, error) {
_ = setFlags(f)
return f, nil
}
// reopenMetadataHandle reopens a handle created by openMetadataHandle for reading.
// The caller must no longer use the original file.
func reopenMetadataHandle(f *os.File) (*os.File, error) {
defer func() {
_ = f.Close()
}()
f2, err := os.OpenFile(linuxFdPath(f.Fd()), O_RDONLY, 0)
if err != nil {
return nil, err
}
defer func() {
_ = f2.Close()
}()
// Duplicate the filehandle and use that to create a file object with the correct name.
// f2 will automatically close its file handle on garbage collection.
fd3, err := syscall.Dup(int(f2.Fd()))
if err != nil {
return nil, err
}
f3 := os.NewFile(uintptr(fd3), f.Name())
_ = setFlags(f3)
return f3, nil
}

View file

@ -95,3 +95,37 @@ func openMetadataHandle(path string, flag int) (*os.File, error) {
}
return os.NewFile(uintptr(handle), path), nil
}
// reopenMetadataHandle reopens a handle created by openMetadataHandle for reading.
// The caller must no longer use the original file.
func reopenMetadataHandle(f *os.File) (*os.File, error) {
defer func() {
_ = f.Close()
}()
fileAccess := windows.FILE_GENERIC_READ
shareMode := windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE
attrs := windows.FILE_ATTRIBUTE_NORMAL | windows.FILE_FLAG_BACKUP_SEMANTICS
// FIXME correct FILE_FLAG_OPEN_REPARSE_POINT handling?
handle, err := reOpenFile(windows.Handle(f.Fd()), uint32(fileAccess), uint32(shareMode), uint32(attrs))
if err != nil {
return nil, err
}
return os.NewFile(uintptr(handle), f.Name()), nil
}
var (
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procReOpenFile = modkernel32.NewProc("ReOpenFile")
)
func reOpenFile(original windows.Handle, access uint32, mode uint32, attrs uint32) (handle windows.Handle, err error) {
r0, _, e1 := syscall.SyscallN(procReOpenFile.Addr(), uintptr(original), uintptr(access), uintptr(mode), uintptr(attrs))
handle = windows.Handle(r0)
if handle == windows.InvalidHandle {
err = errnoErr(e1)
}
return
}