diff --git a/cmd/restic/cmd_backup.go b/cmd/restic/cmd_backup.go index 48a607ecb..c4adec1c2 100644 --- a/cmd/restic/cmd_backup.go +++ b/cmd/restic/cmd_backup.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "path" "path/filepath" "strings" "time" @@ -236,10 +237,16 @@ func readBackupFromStdin(opts BackupOptions, gopts GlobalOptions, args []string) return errors.Fatal("when reading from stdin, no additional files can be specified") } - if opts.StdinFilename == "" { + fn := opts.StdinFilename + + if fn == "" { return errors.Fatal("filename for backup from stdin must not be empty") } + if filepath.Base(fn) != fn || path.Base(fn) != fn { + return errors.Fatal("filename is invalid (may not contain a directory, slash or backslash)") + } + if gopts.password == "" { return errors.Fatal("unable to read password from stdin when data is to be read from stdin, use --password-file or $RESTIC_PASSWORD") } @@ -266,7 +273,7 @@ func readBackupFromStdin(opts BackupOptions, gopts GlobalOptions, args []string) Hostname: opts.Hostname, } - _, id, err := r.Archive(gopts.ctx, opts.StdinFilename, os.Stdin, newArchiveStdinProgress(gopts)) + _, id, err := r.Archive(gopts.ctx, fn, os.Stdin, newArchiveStdinProgress(gopts)) if err != nil { return err } diff --git a/cmd/restic/global.go b/cmd/restic/global.go index 6827f512d..d472d8a34 100644 --- a/cmd/restic/global.go +++ b/cmd/restic/global.go @@ -388,8 +388,10 @@ func OpenRepository(opts GlobalOptions) (*repository.Repository, error) { } } } else { - Verbosef("found %d old cache directories in %v, pass --cleanup-cache to remove them\n", - len(oldCacheDirs), c.Base) + if stdoutIsTerminal() { + Verbosef("found %d old cache directories in %v, pass --cleanup-cache to remove them\n", + len(oldCacheDirs), c.Base) + } } return s, nil diff --git a/internal/fuse/dir.go b/internal/fuse/dir.go index f0c829f1c..dfbff7d4f 100644 --- a/internal/fuse/dir.go +++ b/internal/fuse/dir.go @@ -5,6 +5,7 @@ package fuse import ( "os" + "path/filepath" "bazil.org/fuse" "bazil.org/fuse/fs" @@ -28,6 +29,10 @@ type dir struct { blobsize *BlobSizeCache } +func cleanupNodeName(name string) string { + return filepath.Base(name) +} + func newDir(ctx context.Context, root *Root, inode, parentInode uint64, node *restic.Node) (*dir, error) { debug.Log("new dir for %v (%v)", node.Name, node.Subtree.Str()) tree, err := root.repo.LoadTree(ctx, *node.Subtree) @@ -37,7 +42,7 @@ func newDir(ctx context.Context, root *Root, inode, parentInode uint64, node *re } items := make(map[string]*restic.Node) for _, node := range tree.Nodes { - items[node.Name] = node + items[cleanupNodeName(node.Name)] = node } return &dir{ @@ -84,7 +89,7 @@ func newDirFromSnapshot(ctx context.Context, root *Root, inode uint64, snapshot } for _, node := range nodes { - items[node.Name] = node + items[cleanupNodeName(node.Name)] = node } } @@ -151,6 +156,7 @@ func (d *dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { }) for _, node := range d.items { + name := cleanupNodeName(node.Name) var typ fuse.DirentType switch node.Type { case "dir": @@ -162,9 +168,9 @@ func (d *dir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { } ret = append(ret, fuse.Dirent{ - Inode: fs.GenerateDynamicInode(d.inode, node.Name), + Inode: fs.GenerateDynamicInode(d.inode, name), Type: typ, - Name: node.Name, + Name: name, }) } @@ -176,6 +182,7 @@ func (d *dir) Lookup(ctx context.Context, name string) (fs.Node, error) { node, ok := d.items[name] if !ok { debug.Log(" Lookup(%v) -> not found", name) + debug.Log(" items: %v\n", d.items) return nil, fuse.ENOENT } switch node.Type {