From fa66358b1eb0776c81689e434ec01680053f834c Mon Sep 17 00:00:00 2001 From: Andy Hsu Date: Sun, 9 Jul 2023 14:42:57 +0800 Subject: [PATCH] fix(sftp): read target obj of symlink file (close #4713) --- drivers/sftp/driver.go | 7 +++++-- drivers/sftp/types.go | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/drivers/sftp/driver.go b/drivers/sftp/driver.go index 24e83daa887..d88d1753e8c 100644 --- a/drivers/sftp/driver.go +++ b/drivers/sftp/driver.go @@ -11,6 +11,7 @@ import ( "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/pkg/utils" "github.com/pkg/sftp" + log "github.com/sirupsen/logrus" ) type SFTP struct { @@ -39,13 +40,15 @@ func (d *SFTP) Drop(ctx context.Context) error { } func (d *SFTP) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { + log.Debugf("[sftp] list dir: %s", dir.GetPath()) files, err := d.client.ReadDir(dir.GetPath()) if err != nil { return nil, err } - return utils.SliceConvert(files, func(src os.FileInfo) (model.Obj, error) { - return fileToObj(src), nil + objs, err := utils.SliceConvert(files, func(src os.FileInfo) (model.Obj, error) { + return d.fileToObj(src, dir.GetPath()) }) + return objs, err } func (d *SFTP) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { diff --git a/drivers/sftp/types.go b/drivers/sftp/types.go index 819ab168237..70a03b983ab 100644 --- a/drivers/sftp/types.go +++ b/drivers/sftp/types.go @@ -2,15 +2,44 @@ package sftp import ( "os" + stdpath "path" + "strings" "github.com/alist-org/alist/v3/internal/model" + log "github.com/sirupsen/logrus" ) -func fileToObj(f os.FileInfo) model.Obj { - return &model.Object{ +func (d *SFTP) fileToObj(f os.FileInfo, dir string) (model.Obj, error) { + symlink := f.Mode()&os.ModeSymlink != 0 + if !symlink { + return &model.Object{ + Name: f.Name(), + Size: f.Size(), + Modified: f.ModTime(), + IsFolder: f.IsDir(), + }, nil + } + path := stdpath.Join(dir, f.Name()) + // set target path + target, err := d.client.ReadLink(path) + if err != nil { + return nil, err + } + if !strings.HasPrefix(target, "/") { + target = stdpath.Join(dir, target) + } + _f, err := d.client.Stat(target) + if err != nil { + return nil, err + } + // set basic info + obj := &model.Object{ Name: f.Name(), - Size: f.Size(), - Modified: f.ModTime(), - IsFolder: f.IsDir(), + Size: _f.Size(), + Modified: _f.ModTime(), + IsFolder: _f.IsDir(), + Path: target, } + log.Debugf("[sftp] obj: %+v, is symlink: %v", obj, symlink) + return obj, nil }