mirror of
https://github.com/restic/restic.git
synced 2025-03-30 00:00:14 +01:00
62 lines
1.3 KiB
Go
62 lines
1.3 KiB
Go
package fs
|
|
|
|
import (
|
|
"os"
|
|
"syscall"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func openMetadataHandle(path string, flag int) (*os.File, error) {
|
|
// O_PATH|O_NOFOLLOW is necessary to also be able to get a handle to symlinks
|
|
flags := unix.O_PATH
|
|
if flag&O_NOFOLLOW != 0 {
|
|
flags |= O_NOFOLLOW
|
|
}
|
|
if flag&O_DIRECTORY != 0 {
|
|
flags |= O_DIRECTORY
|
|
}
|
|
|
|
f, err := os.OpenFile(path, flags, 0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_ = setFlags(f)
|
|
return f, nil
|
|
}
|
|
|
|
func openReadHandle(path string, flag int) (*os.File, error) {
|
|
f, err := os.OpenFile(path, flag, 0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_ = 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
|
|
}
|