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:
parent
c0d727dfed
commit
f1ae5a21e2
3 changed files with 68 additions and 0 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue