tree: fix display of files with illegal Windows file system names

Before this change, files with illegal Windows names (eg those
containing \) would not be displayed properly in tree.

This change adds the local encoding to the Windows file names so \
will be displayed as its wide unicode equivalent.

See: https://forum.rclone.org/t/error-with-build-v1-61-1-tree-command-panic-runtime-error-invalid-memory-address-or-nil-pointer-dereference/35922/
This commit is contained in:
Nick Craig-Wood 2023-02-08 17:17:55 +00:00
parent 1d0c75b0c2
commit fb4600f6f9

View File

@ -18,6 +18,7 @@ import (
"github.com/rclone/rclone/fs/dirtree" "github.com/rclone/rclone/fs/dirtree"
"github.com/rclone/rclone/fs/log" "github.com/rclone/rclone/fs/log"
"github.com/rclone/rclone/fs/walk" "github.com/rclone/rclone/fs/walk"
"github.com/rclone/rclone/lib/encoder"
"github.com/rclone/rclone/lib/terminal" "github.com/rclone/rclone/lib/terminal"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -27,6 +28,7 @@ var (
outFileName string outFileName string
noReport bool noReport bool
sort string sort string
enc = encoder.OS
) )
func init() { func init() {
@ -163,7 +165,7 @@ type FileInfo struct {
// Name is base name of the file // Name is base name of the file
func (to *FileInfo) Name() string { func (to *FileInfo) Name() string {
return path.Base(to.entry.Remote()) return enc.FromStandardName(path.Base(to.entry.Remote()))
} }
// Size in bytes for regular files; system-dependent for others // Size in bytes for regular files; system-dependent for others
@ -197,7 +199,7 @@ func (to *FileInfo) Sys() interface{} {
// String returns the full path // String returns the full path
func (to *FileInfo) String() string { func (to *FileInfo) String() string {
return to.entry.Remote() return filepath.FromSlash(enc.FromStandardPath(to.entry.Remote()))
} }
// Fs maps an fs.Fs into a tree.Fs // Fs maps an fs.Fs into a tree.Fs
@ -212,6 +214,7 @@ func NewFs(dirs dirtree.DirTree) Fs {
func (dirs Fs) Stat(filePath string) (fi os.FileInfo, err error) { func (dirs Fs) Stat(filePath string) (fi os.FileInfo, err error) {
defer log.Trace(nil, "filePath=%q", filePath)("fi=%+v, err=%v", &fi, &err) defer log.Trace(nil, "filePath=%q", filePath)("fi=%+v, err=%v", &fi, &err)
filePath = filepath.ToSlash(filePath) filePath = filepath.ToSlash(filePath)
filePath = enc.ToStandardPath(filePath)
filePath = strings.TrimLeft(filePath, "/") filePath = strings.TrimLeft(filePath, "/")
if filePath == "" { if filePath == "" {
return &FileInfo{fs.NewDir("", time.Now())}, nil return &FileInfo{fs.NewDir("", time.Now())}, nil
@ -227,13 +230,14 @@ func (dirs Fs) Stat(filePath string) (fi os.FileInfo, err error) {
func (dirs Fs) ReadDir(dir string) (names []string, err error) { func (dirs Fs) ReadDir(dir string) (names []string, err error) {
defer log.Trace(nil, "dir=%s", dir)("names=%+v, err=%v", &names, &err) defer log.Trace(nil, "dir=%s", dir)("names=%+v, err=%v", &names, &err)
dir = filepath.ToSlash(dir) dir = filepath.ToSlash(dir)
dir = enc.ToStandardPath(dir)
dir = strings.TrimLeft(dir, "/") dir = strings.TrimLeft(dir, "/")
entries, ok := dirs[dir] entries, ok := dirs[dir]
if !ok { if !ok {
return nil, fmt.Errorf("couldn't find directory %q", dir) return nil, fmt.Errorf("couldn't find directory %q", dir)
} }
for _, entry := range entries { for _, entry := range entries {
names = append(names, path.Base(entry.Remote())) names = append(names, enc.FromStandardName(path.Base(entry.Remote())))
} }
return return
} }