fs: remove Stat from FS interface
This commit is contained in:
parent
623ba92b98
commit
2f2ce9add2
6 changed files with 37 additions and 51 deletions
|
@ -605,22 +605,6 @@ func join(elem ...string) string {
|
||||||
return path.Join(elem...)
|
return path.Join(elem...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// statDir returns the file info for the directory. Symbolic links are
|
|
||||||
// resolved. If the target directory is not a directory, an error is returned.
|
|
||||||
func (arch *Archiver) statDir(dir string) (os.FileInfo, error) {
|
|
||||||
fi, err := arch.FS.Stat(dir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tpe := fi.Mode() & (os.ModeType | os.ModeCharDevice)
|
|
||||||
if tpe != os.ModeDir {
|
|
||||||
return fi, errors.Errorf("path is not a directory: %v", dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fi, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// saveTree stores a Tree in the repo, returned is the tree. snPath is the path
|
// saveTree stores a Tree in the repo, returned is the tree. snPath is the path
|
||||||
// within the current snapshot.
|
// within the current snapshot.
|
||||||
func (arch *Archiver) saveTree(ctx context.Context, snPath string, atree *tree, previous *restic.Tree, complete fileCompleteFunc) (futureNode, int, error) {
|
func (arch *Archiver) saveTree(ctx context.Context, snPath string, atree *tree, previous *restic.Tree, complete fileCompleteFunc) (futureNode, int, error) {
|
||||||
|
@ -631,15 +615,8 @@ func (arch *Archiver) saveTree(ctx context.Context, snPath string, atree *tree,
|
||||||
return futureNode{}, 0, errors.Errorf("FileInfoPath for %v is empty", snPath)
|
return futureNode{}, 0, errors.Errorf("FileInfoPath for %v is empty", snPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
fi, err := arch.statDir(atree.FileInfoPath)
|
var err error
|
||||||
if err != nil {
|
node, err = arch.dirPathToNode(snPath, atree.FileInfoPath)
|
||||||
return futureNode{}, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
debug.Log("%v, dir node data loaded from %v", snPath, atree.FileInfoPath)
|
|
||||||
// in some cases reading xattrs for directories above the backup source is not allowed
|
|
||||||
// thus ignore errors for such folders.
|
|
||||||
node, err = arch.nodeFromFileInfo(snPath, atree.FileInfoPath, fi, true)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return futureNode{}, 0, err
|
return futureNode{}, 0, err
|
||||||
}
|
}
|
||||||
|
@ -710,6 +687,36 @@ func (arch *Archiver) saveTree(ctx context.Context, snPath string, atree *tree,
|
||||||
return fn, len(nodes), nil
|
return fn, len(nodes), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (arch *Archiver) dirPathToNode(snPath, target string) (node *restic.Node, err error) {
|
||||||
|
meta, err := arch.FS.OpenFile(target, fs.O_RDONLY)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
cerr := meta.Close()
|
||||||
|
if err == nil {
|
||||||
|
err = cerr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
debug.Log("%v, reading dir node data from %v", snPath, target)
|
||||||
|
fi, err := meta.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// in some cases reading xattrs for directories above the backup source is not allowed
|
||||||
|
// thus ignore errors for such folders.
|
||||||
|
node, err = arch.nodeFromFileInfo(snPath, target, fi, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if node.Type != restic.NodeTypeDir {
|
||||||
|
return nil, errors.Errorf("path is not a directory: %v", target)
|
||||||
|
}
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
|
||||||
// resolveRelativeTargets replaces targets that only contain relative
|
// resolveRelativeTargets replaces targets that only contain relative
|
||||||
// directories ("." or "../../") with the contents of the directory. Each
|
// directories ("." or "../../") with the contents of the directory. Each
|
||||||
// element of target is processed with fs.Clean().
|
// element of target is processed with fs.Clean().
|
||||||
|
|
|
@ -34,12 +34,6 @@ func (fs Local) OpenFile(name string, flag int) (File, error) {
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns a FileInfo describing the named file. If there is an error, it
|
|
||||||
// will be of type *PathError.
|
|
||||||
func (fs Local) Stat(name string) (os.FileInfo, error) {
|
|
||||||
return os.Stat(fixpath(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lstat returns the FileInfo structure describing the named file.
|
// Lstat returns the FileInfo structure describing the named file.
|
||||||
// If the file is a symbolic link, the returned FileInfo
|
// If the file is a symbolic link, the returned FileInfo
|
||||||
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
||||||
|
|
|
@ -131,11 +131,6 @@ func (fs *LocalVss) OpenFile(name string, flag int) (File, error) {
|
||||||
return fs.FS.OpenFile(fs.snapshotPath(name), flag)
|
return fs.FS.OpenFile(fs.snapshotPath(name), flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat wraps the Stat method of the underlying file system.
|
|
||||||
func (fs *LocalVss) Stat(name string) (os.FileInfo, error) {
|
|
||||||
return fs.FS.Stat(fs.snapshotPath(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lstat wraps the Lstat method of the underlying file system.
|
// Lstat wraps the Lstat method of the underlying file system.
|
||||||
func (fs *LocalVss) Lstat(name string) (os.FileInfo, error) {
|
func (fs *LocalVss) Lstat(name string) (os.FileInfo, error) {
|
||||||
return fs.FS.Lstat(fs.snapshotPath(name))
|
return fs.FS.Lstat(fs.snapshotPath(name))
|
||||||
|
|
|
@ -317,16 +317,12 @@ func TestVSSFS(t *testing.T) {
|
||||||
|
|
||||||
// trigger snapshot creation and
|
// trigger snapshot creation and
|
||||||
// capture FI while file still exists (should already be within the snapshot)
|
// capture FI while file still exists (should already be within the snapshot)
|
||||||
origFi, err := localVss.Stat(tempfile)
|
origFi, err := localVss.Lstat(tempfile)
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
|
|
||||||
// remove original file
|
// remove original file
|
||||||
rtest.OK(t, os.Remove(tempfile))
|
rtest.OK(t, os.Remove(tempfile))
|
||||||
|
|
||||||
statFi, err := localVss.Stat(tempfile)
|
|
||||||
rtest.OK(t, err)
|
|
||||||
rtest.Equals(t, origFi.Mode(), statFi.Mode())
|
|
||||||
|
|
||||||
lstatFi, err := localVss.Lstat(tempfile)
|
lstatFi, err := localVss.Lstat(tempfile)
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
rtest.Equals(t, origFi.Mode(), lstatFi.Mode())
|
rtest.Equals(t, origFi.Mode(), lstatFi.Mode())
|
||||||
|
@ -336,9 +332,10 @@ func TestVSSFS(t *testing.T) {
|
||||||
data, err := io.ReadAll(f)
|
data, err := io.ReadAll(f)
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
rtest.Equals(t, "example", string(data), "unexpected file content")
|
rtest.Equals(t, "example", string(data), "unexpected file content")
|
||||||
rtest.OK(t, f.Close())
|
|
||||||
|
|
||||||
node, err := localVss.NodeFromFileInfo(tempfile, statFi, false)
|
node, err := f.ToNode(false)
|
||||||
rtest.OK(t, err)
|
rtest.OK(t, err)
|
||||||
rtest.Equals(t, node.Mode, statFi.Mode())
|
rtest.Equals(t, node.Mode, lstatFi.Mode())
|
||||||
|
|
||||||
|
rtest.OK(t, f.Close())
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,12 +81,6 @@ func (fs *Reader) OpenFile(name string, flag int) (f File, err error) {
|
||||||
return nil, pathError("open", name, syscall.ENOENT)
|
return nil, pathError("open", name, syscall.ENOENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat returns a FileInfo describing the named file. If there is an error, it
|
|
||||||
// will be of type *os.PathError.
|
|
||||||
func (fs *Reader) Stat(name string) (os.FileInfo, error) {
|
|
||||||
return fs.Lstat(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lstat returns the FileInfo structure describing the named file.
|
// Lstat returns the FileInfo structure describing the named file.
|
||||||
// If the file is a symbolic link, the returned FileInfo
|
// If the file is a symbolic link, the returned FileInfo
|
||||||
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
// FS bundles all methods needed for a file system.
|
// FS bundles all methods needed for a file system.
|
||||||
type FS interface {
|
type FS interface {
|
||||||
OpenFile(name string, flag int) (File, error)
|
OpenFile(name string, flag int) (File, error)
|
||||||
Stat(name string) (os.FileInfo, error)
|
|
||||||
Lstat(name string) (os.FileInfo, error)
|
Lstat(name string) (os.FileInfo, error)
|
||||||
DeviceID(fi os.FileInfo) (deviceID uint64, err error)
|
DeviceID(fi os.FileInfo) (deviceID uint64, err error)
|
||||||
ExtendedStat(fi os.FileInfo) ExtendedFileInfo
|
ExtendedStat(fi os.FileInfo) ExtendedFileInfo
|
||||||
|
|
Loading…
Reference in a new issue