mirror of https://github.com/restic/restic.git
fs: Handle absolute pathname for --stdin-filename
Return valid directory info from Lstat() for parent directories of the specified filename. Previously only "/" and "." were valid directories. Also set directory mode as this is checked by archiver. Closes #2063
This commit is contained in:
parent
f7f14cf8c9
commit
8066195e6e
|
@ -0,0 +1,6 @@
|
|||
Bugfix: Allow absolute path for filename when backing up from stdin
|
||||
|
||||
When backing up from stdin, handle directory path for `--stdin-filename`.
|
||||
This can be used to specify the full path for the backed-up file.
|
||||
|
||||
https://github.com/restic/restic/issues/2063
|
|
@ -103,17 +103,32 @@ func (fs *Reader) Stat(name string) (os.FileInfo, error) {
|
|||
// describes the symbolic link. Lstat makes no attempt to follow the link.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
func (fs *Reader) Lstat(name string) (os.FileInfo, error) {
|
||||
getDirInfo := func(name string) os.FileInfo {
|
||||
fi := fakeFileInfo{
|
||||
name: fs.Base(name),
|
||||
size: 0,
|
||||
mode: os.ModeDir | 0755,
|
||||
modtime: time.Now(),
|
||||
}
|
||||
return fi
|
||||
}
|
||||
|
||||
switch name {
|
||||
case fs.Name:
|
||||
return fs.fi(), nil
|
||||
case "/", ".":
|
||||
fi := fakeFileInfo{
|
||||
name: name,
|
||||
size: 0,
|
||||
mode: 0755,
|
||||
modtime: time.Now(),
|
||||
return getDirInfo(name), nil
|
||||
}
|
||||
|
||||
dir := fs.Dir(fs.Name)
|
||||
for {
|
||||
if dir == "/" || dir == "." {
|
||||
break
|
||||
}
|
||||
return fi, nil
|
||||
if name == dir {
|
||||
return getDirInfo(name), nil
|
||||
}
|
||||
dir = fs.Dir(dir)
|
||||
}
|
||||
|
||||
return nil, os.ErrNotExist
|
||||
|
|
|
@ -270,7 +270,7 @@ func TestFSReader(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkFileInfo(t, fi, "/", time.Time{}, 0755, false)
|
||||
checkFileInfo(t, fi, "/", time.Time{}, os.ModeDir|0755, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -281,7 +281,16 @@ func TestFSReader(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkFileInfo(t, fi, ".", time.Time{}, 0755, false)
|
||||
checkFileInfo(t, fi, ".", time.Time{}, os.ModeDir|0755, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dir/Lstat-error-not-exist",
|
||||
f: func(t *testing.T, fs FS) {
|
||||
_, err := fs.Lstat("other")
|
||||
if err != os.ErrNotExist {
|
||||
t.Fatal(err)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -292,7 +301,7 @@ func TestFSReader(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkFileInfo(t, fi, "/", time.Time{}, 0755, false)
|
||||
checkFileInfo(t, fi, "/", time.Time{}, os.ModeDir|0755, true)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -303,7 +312,7 @@ func TestFSReader(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkFileInfo(t, fi, ".", time.Time{}, 0755, false)
|
||||
checkFileInfo(t, fi, ".", time.Time{}, os.ModeDir|0755, true)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -324,6 +333,54 @@ func TestFSReader(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFSReaderDir(t *testing.T) {
|
||||
data := test.Random(55, 1<<18+588)
|
||||
now := time.Now()
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
filename string
|
||||
}{
|
||||
{
|
||||
name: "Lstat-absolute",
|
||||
filename: "/path/to/foobar",
|
||||
},
|
||||
{
|
||||
name: "Lstat-relative",
|
||||
filename: "path/to/foobar",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
fs := &Reader{
|
||||
Name: test.filename,
|
||||
ReadCloser: ioutil.NopCloser(bytes.NewReader(data)),
|
||||
|
||||
Mode: 0644,
|
||||
Size: int64(len(data)),
|
||||
ModTime: now,
|
||||
}
|
||||
|
||||
dir := path.Dir(fs.Name)
|
||||
for {
|
||||
if dir == "/" || dir == "." {
|
||||
break
|
||||
}
|
||||
|
||||
fi, err := fs.Lstat(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
checkFileInfo(t, fi, dir, time.Time{}, os.ModeDir|0755, true)
|
||||
|
||||
dir = path.Dir(dir)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFSReaderMinFileSize(t *testing.T) {
|
||||
var tests = []struct {
|
||||
name string
|
||||
|
|
Loading…
Reference in New Issue