sftpgo: fix compatibility issues with rclone

This commit is contained in:
2025-09-21 01:25:26 +00:00
parent ea40bbd417
commit 4d7a8f43da
3 changed files with 26 additions and 13 deletions

View File

@@ -65,9 +65,17 @@ in
# ftp LIST operation returns entries over-the-wire like: # ftp LIST operation returns entries over-the-wire like:
# - dgrwxrwxr-x 1 ftp ftp 9 Apr 9 15:05 Videos # - dgrwxrwxr-x 1 ftp ftp 9 Apr 9 15:05 Videos
# however not all clients understand all mode bits (like that `g`, indicating SGID / group sticky bit). # however not all clients understand all mode bits (like that `g`, indicating SGID / group sticky bit).
# - e.g. Kodi will sliently not display entries with `g`.
# instead, only send mode bits which are well-understood. # instead, only send mode bits which are well-understood.
# the full set of bits, from which i filter, is found here: <https://pkg.go.dev/io/fs#FileMode> # the full set of bits, from which i filter, is found here: <https://pkg.go.dev/io/fs#FileMode>
./safe_fileinfo.patch #
# PATCH NOTES:
# - i *think* os.FileInfo contains the bad mode bits, and anything that goes through `vfs.NewFileInfo` gets those bits stripped (good).
# - for readdir, `patternDirLister` is just an easily accessible interface which causes the os.FileInfo's to be converted through `vfs.NewFileInfo`.
# - if patched incorrectly, sftpgo may return absolute paths for operations like `ls foo/bar/` (breaks rclone)
./safe_fileinfo_readdir.patch
# XXX(2025-09-20): nothing seems to break in Kodi when i leave `Stat` unpatched
# ./safe_fileinfo_stat.patch
]; ];
}); });

View File

@@ -2,29 +2,21 @@ diff --git a/internal/ftpd/handler.go b/internal/ftpd/handler.go
index 036c3977..33211261 100644 index 036c3977..33211261 100644
--- a/internal/ftpd/handler.go --- a/internal/ftpd/handler.go
+++ b/internal/ftpd/handler.go +++ b/internal/ftpd/handler.go
@@ -169,7 +169,7 @@ func (c *Connection) Stat(name string) (os.FileInfo, error) { @@ -315,7 +315,18 @@ func (c *Connection) ReadDir(name string) (ftpserver.DirLister, error) {
}
return nil, err
}
- return fi, nil
+ return vfs.NewFileInfo(name, fi.IsDir(), fi.Size(), fi.ModTime(), false), nil
}
// Name returns the name of this connection
@@ -315,7 +315,17 @@ func (c *Connection) ReadDir(name string) (ftpserver.DirLister, error) {
}, nil }, nil
} }
- return c.ListDir(name) - return c.ListDir(name)
+ c.clientContext.SetListPath(name) //< MIGHT not be required
+ lister, err := c.ListDir(name) + lister, err := c.ListDir(name)
+ if err != nil { + if err != nil {
+ return nil, err + return nil, err
+ } + }
+ return &patternDirLister{ + return &patternDirLister{ // this idiom is copied from 10 lines up ^
+ DirLister: lister, + DirLister: lister,
+ pattern: "*", + pattern: "*",
+ lastCommand: c.clientContext.GetLastCommand(), + lastCommand: c.clientContext.GetLastCommand(),
+ dirName: name, + dirName: "", //< or set to `c.clientContext.Path()`? returned paths are relative to this dirName.
+ connectionPath: c.clientContext.Path(), + connectionPath: c.clientContext.Path(),
+ }, nil + }, nil
} }

View File

@@ -0,0 +1,13 @@
diff --git a/internal/ftpd/handler.go b/internal/ftpd/handler.go
index 036c3977..33211261 100644
--- a/internal/ftpd/handler.go
+++ b/internal/ftpd/handler.go
@@ -169,7 +169,7 @@ func (c *Connection) Stat(name string) (os.FileInfo, error) {
}
return nil, err
}
- return fi, nil
+ return vfs.NewFileInfo(name, fi.IsDir(), fi.Size(), fi.ModTime(), false), nil
}
// Name returns the name of this connection