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/log"
"github.com/rclone/rclone/fs/walk"
"github.com/rclone/rclone/lib/encoder"
"github.com/rclone/rclone/lib/terminal"
"github.com/spf13/cobra"
)
@ -27,6 +28,7 @@ var (
outFileName string
noReport bool
sort string
enc = encoder.OS
)
func init() {
@ -163,7 +165,7 @@ type FileInfo struct {
// Name is base name of the file
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
@ -197,7 +199,7 @@ func (to *FileInfo) Sys() interface{} {
// String returns the full path
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
@ -212,6 +214,7 @@ func NewFs(dirs dirtree.DirTree) Fs {
func (dirs Fs) Stat(filePath string) (fi os.FileInfo, err error) {
defer log.Trace(nil, "filePath=%q", filePath)("fi=%+v, err=%v", &fi, &err)
filePath = filepath.ToSlash(filePath)
filePath = enc.ToStandardPath(filePath)
filePath = strings.TrimLeft(filePath, "/")
if filePath == "" {
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) {
defer log.Trace(nil, "dir=%s", dir)("names=%+v, err=%v", &names, &err)
dir = filepath.ToSlash(dir)
dir = enc.ToStandardPath(dir)
dir = strings.TrimLeft(dir, "/")
entries, ok := dirs[dir]
if !ok {
return nil, fmt.Errorf("couldn't find directory %q", dir)
}
for _, entry := range entries {
names = append(names, path.Base(entry.Remote()))
names = append(names, enc.FromStandardName(path.Base(entry.Remote())))
}
return
}