1
0
Fork 0
mirror of https://github.com/restic/restic.git synced 2025-03-09 13:53:03 +00:00

fs: wire up fd-based handles for fs.Local

This commit is contained in:
Michael Eischer 2024-11-17 13:52:42 +01:00
parent 1b87468531
commit 4b33540148
3 changed files with 112 additions and 46 deletions

View file

@ -29,7 +29,7 @@ func (fs Local) VolumeName(path string) string {
//
// Only the O_NOFOLLOW and O_DIRECTORY flags are supported.
func (fs Local) OpenFile(name string, flag int, metadataOnly bool) (File, error) {
return newLocalFile(name, flag, metadataOnly)
return buildLocalFile(name, flag, metadataOnly)
}
// Lstat returns the FileInfo structure describing the named file.
@ -85,52 +85,14 @@ func (fs Local) Dir(path string) string {
return filepath.Dir(path)
}
// See the File interface for a description of each method
type localFile struct {
name string
flag int
f *os.File
fi *ExtendedFileInfo
meta metadataHandle
}
// See the File interface for a description of each method
var _ File = &localFile{}
func newLocalFile(name string, flag int, metadataOnly bool) (*localFile, error) {
meta := newPathMetadataHandle(name, flag)
var f *os.File
if !metadataOnly {
var err error
f, err = os.OpenFile(fixpath(name), flag, 0)
if err != nil {
return nil, err
}
_ = setFlags(f)
}
file := &localFile{
name: name,
flag: flag,
f: f,
meta: meta,
}
return file, nil
}
func (f *localFile) MakeReadable() error {
if f.f != nil {
panic("file is already readable")
}
newF, err := newLocalFile(f.name, f.flag, false)
if err != nil {
return err
}
// replace state and also reset cached FileInfo
*f = *newF
return nil
}
func (f *localFile) cacheFI() error {
if f.fi != nil {
return nil
@ -186,3 +148,104 @@ type cachedMetadataHandle struct {
func (c *cachedMetadataHandle) Stat() (*ExtendedFileInfo, error) {
return c.f.Stat()
}
type pathLocalFile struct {
localFile
flag int
}
var _ File = &pathLocalFile{}
func newPathLocalFile(name string, flag int, metadataOnly bool) (*pathLocalFile, error) {
var f *os.File
var meta metadataHandle
if !metadataOnly {
var err error
f, err = os.OpenFile(fixpath(name), flag, 0)
if err != nil {
return nil, err
}
_ = setFlags(f)
}
meta = newPathMetadataHandle(name, flag)
return &pathLocalFile{
localFile: localFile{
name: name,
f: f,
meta: meta,
},
flag: flag,
}, nil
}
func (f *pathLocalFile) MakeReadable() error {
if f.f != nil {
panic("file is already readable")
}
newF, err := newPathLocalFile(f.name, f.flag, false)
if err != nil {
return err
}
// replace state and also reset cached FileInfo
*f = *newF
return nil
}
type fdLocalFile struct {
localFile
flag int
metadataOnly bool
}
var _ File = &fdLocalFile{}
func newFdLocalFile(name string, flag int, metadataOnly bool) (*fdLocalFile, error) {
var f *os.File
var err error
if metadataOnly {
f, err = openMetadataHandle(name, flag)
} else {
f, err = openReadHandle(name, flag)
}
if err != nil {
return nil, err
}
meta := newFdMetadataHandle(name, f)
return &fdLocalFile{
localFile: localFile{
name: name,
f: f,
meta: meta,
},
flag: flag,
metadataOnly: metadataOnly,
}, nil
}
func (f *fdLocalFile) MakeReadable() error {
if !f.metadataOnly {
panic("file is already readable")
}
newF, err := reopenMetadataHandle(f.f)
// old handle is no longer usable
f.f = nil
if err != nil {
return err
}
f.f = newF
f.meta = newFdMetadataHandle(f.name, newF)
f.metadataOnly = false
return nil
}
func buildLocalFile(name string, flag int, metadataOnly bool) (File, error) {
useFd := true // FIXME
if useFd {
return newFdLocalFile(name, flag, metadataOnly)
}
return newPathLocalFile(name, flag, metadataOnly)
}

View file

@ -96,7 +96,8 @@ func checkMetadata(t *testing.T, f File, path string, follow bool, nodeType rest
func assertFIEqual(t *testing.T, want os.FileInfo, got *ExtendedFileInfo) {
t.Helper()
rtest.Equals(t, want.Name(), got.Name, "Name")
// do not compare the name as it can differ in testcases that rename the test file
// a fd-based implementation will still keep the original file name
rtest.Equals(t, want.ModTime(), got.ModTime, "ModTime")
rtest.Equals(t, want.Mode(), got.Mode, "Mode")
rtest.Equals(t, want.Size(), got.Size, "Size")

View file

@ -23,11 +23,13 @@ func (p *fdMetadataHandle) Name() string {
}
func (p *fdMetadataHandle) Stat() (*ExtendedFileInfo, error) {
fi, err := p.f.Stat()
if err != nil {
return nil, err
}
return extendedStat(fi), nil
// localFile.cacheFI() already internally calls stat on the filehandle
panic("should never be called")
// fi, err := p.f.Stat()
// if err != nil {
// return nil, err
// }
// return extendedStat(fi), nil
}
func (p *fdMetadataHandle) Readlink() (string, error) {