diff --git a/cmd/restic/cmd_backup.go b/cmd/restic/cmd_backup.go index 62f2184ae..acb5500fd 100644 --- a/cmd/restic/cmd_backup.go +++ b/cmd/restic/cmd_backup.go @@ -591,10 +591,13 @@ func runBackup(ctx context.Context, opts BackupOptions, gopts GlobalOptions, ter return err } } - targetFS = fs.NewReader(filename, source, fs.ReaderOptions{ + targetFS, err = fs.NewReader(filename, source, fs.ReaderOptions{ ModTime: timeStamp, Mode: 0644, }) + if err != nil { + return fmt.Errorf("failed to backup from stdin: %w", err) + } targets = []string{filename} } diff --git a/internal/archiver/archiver_test.go b/internal/archiver/archiver_test.go index 7b511ec84..906c83011 100644 --- a/internal/archiver/archiver_test.go +++ b/internal/archiver/archiver_test.go @@ -174,10 +174,11 @@ func TestArchiverSaveFileReaderFS(t *testing.T) { ts := time.Now() filename := "xx" - readerFs := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ + readerFs, err := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ ModTime: ts, Mode: 0123, }) + rtest.OK(t, err) node, stats := saveFile(t, repo, filename, readerFs) @@ -286,11 +287,11 @@ func TestArchiverSaveReaderFS(t *testing.T) { ts := time.Now() filename := "xx" - readerFs := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ + readerFs, err := fs.NewReader(filename, io.NopCloser(strings.NewReader(test.Data)), fs.ReaderOptions{ ModTime: ts, Mode: 0123, }) - + rtest.OK(t, err) arch := New(repo, readerFs, Options{}) arch.Error = func(item string, err error) error { t.Errorf("archiver error for %v: %v", item, err) diff --git a/internal/fs/fs_reader.go b/internal/fs/fs_reader.go index 97e09d1d2..c4e98be0f 100644 --- a/internal/fs/fs_reader.go +++ b/internal/fs/fs_reader.go @@ -42,9 +42,12 @@ type readerItem struct { // statically ensure that Local implements FS. var _ FS = &Reader{} -func NewReader(name string, r io.ReadCloser, opts ReaderOptions) *Reader { +func NewReader(name string, r io.ReadCloser, opts ReaderOptions) (*Reader, error) { items := make(map[string]readerItem) name = readerCleanPath(name) + if name == "/" { + return nil, fmt.Errorf("invalid filename specified") + } isFile := true for { @@ -89,7 +92,7 @@ func NewReader(name string, r io.ReadCloser, opts ReaderOptions) *Reader { } return &Reader{ items: items, - } + }, nil } func readerCleanPath(name string) string { diff --git a/internal/fs/fs_reader_test.go b/internal/fs/fs_reader_test.go index bde097d5c..083e8a1a5 100644 --- a/internal/fs/fs_reader_test.go +++ b/internal/fs/fs_reader_test.go @@ -185,15 +185,16 @@ func TestFSReader(t *testing.T) { tests = append(tests, createFileTest(filename, now, data)...) tests = append(tests, createDirTest("", now)...) - for _, test := range tests { - fs := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ + for _, tst := range tests { + fs, err := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, }) + test.OK(t, err) - t.Run(test.name, func(t *testing.T) { - test.f(t, fs) + t.Run(tst.name, func(t *testing.T) { + tst.f(t, fs) }) } } @@ -211,15 +212,16 @@ func TestFSReaderNested(t *testing.T) { tests = append(tests, createDirTest("foo", now)...) tests = append(tests, createDirTest("foo/sub", now)...) - for _, test := range tests { - fs := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ + for _, tst := range tests { + fs, err := NewReader(filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, }) + test.OK(t, err) - t.Run(test.name, func(t *testing.T) { - test.f(t, fs) + t.Run(tst.name, func(t *testing.T) { + tst.f(t, fs) }) } } @@ -244,12 +246,12 @@ func TestFSReaderDir(t *testing.T) { for _, tst := range tests { t.Run(tst.name, func(t *testing.T) { - fs := NewReader(tst.filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ + fs, err := NewReader(tst.filename, io.NopCloser(bytes.NewReader(data)), ReaderOptions{ Mode: 0644, Size: int64(len(data)), ModTime: now, }) - + test.OK(t, err) dir := path.Dir(tst.filename) for { if dir == "/" || dir == "." { @@ -294,12 +296,12 @@ func TestFSReaderMinFileSize(t *testing.T) { for _, tst := range tests { t.Run(tst.name, func(t *testing.T) { - fs := NewReader("testfile", io.NopCloser(strings.NewReader(tst.data)), ReaderOptions{ + fs, err := NewReader("testfile", io.NopCloser(strings.NewReader(tst.data)), ReaderOptions{ Mode: 0644, ModTime: time.Now(), AllowEmptyFile: tst.allowEmpty, }) - + test.OK(t, err) f, err := fs.OpenFile("testfile", O_RDONLY, false) test.OK(t, err) diff --git a/internal/restorer/restorer_test.go b/internal/restorer/restorer_test.go index cd0307359..0b5e34d12 100644 --- a/internal/restorer/restorer_test.go +++ b/internal/restorer/restorer_test.go @@ -908,11 +908,12 @@ func TestRestorerSparseFiles(t *testing.T) { var zeros [1<<20 + 13]byte - target := fs.NewReader("/zeros", io.NopCloser(bytes.NewReader(zeros[:])), fs.ReaderOptions{ + target, err := fs.NewReader("/zeros", io.NopCloser(bytes.NewReader(zeros[:])), fs.ReaderOptions{ Mode: 0600, }) + rtest.OK(t, err) sc := archiver.NewScanner(target) - err := sc.Scan(context.TODO(), []string{"/zeros"}) + err = sc.Scan(context.TODO(), []string{"/zeros"}) rtest.OK(t, err) arch := archiver.New(repo, target, archiver.Options{})