ftpd: support rootless filesystems

This commit is contained in:
ed 2022-02-13 16:38:24 +01:00
parent 6ce0e2cd5b
commit b8453c3b4f
2 changed files with 16 additions and 7 deletions

View file

@ -634,6 +634,7 @@ an FTP server can be started using `--ftp 3921`, and/or `--ftps` for explicit T
* uploads are not resumable -- delete and restart if necessary * uploads are not resumable -- delete and restart if necessary
* runs in active mode by default, you probably want `--ftp-pr 12000-13000` * runs in active mode by default, you probably want `--ftp-pr 12000-13000`
* if you enable both `ftp` and `ftps`, the port-range will be divided in half * if you enable both `ftp` and `ftps`, the port-range will be divided in half
* some older software (filezilla on debian-stable) cannot passive-mode with TLS
## file indexing ## file indexing

View file

@ -18,11 +18,9 @@ from pyftpdlib.log import config_logging
from .__init__ import E from .__init__ import E
from .util import Pebkac, fsenc, exclude_dotfiles from .util import Pebkac, fsenc, exclude_dotfiles
from .bos import bos from .bos import bos
from .authsrv import AuthSrv
if TYPE_CHECKING: if TYPE_CHECKING:
from .svchub import SvcHub from .svchub import SvcHub
from .authsrv import AuthSrv
class FtpAuth(DummyAuthorizer): class FtpAuth(DummyAuthorizer):
@ -82,6 +80,9 @@ class FtpFs(AbstractedFS):
try: try:
vpath = vpath.replace("\\", "/").lstrip("/") vpath = vpath.replace("\\", "/").lstrip("/")
vfs, rem = self.hub.asrv.vfs.get(vpath, self.uname, r, w, m, d) vfs, rem = self.hub.asrv.vfs.get(vpath, self.uname, r, w, m, d)
if not vfs.realpath:
raise FilesystemError("no filesystem mounted at this path")
return os.path.join(vfs.realpath, rem) return os.path.join(vfs.realpath, rem)
except Pebkac as ex: except Pebkac as ex:
raise FilesystemError(str(ex)) raise FilesystemError(str(ex))
@ -125,8 +126,8 @@ class FtpFs(AbstractedFS):
bos.mkdir(ap) bos.mkdir(ap)
def listdir(self, path): def listdir(self, path):
try:
vpath = join(self.cwd, path).lstrip("/") vpath = join(self.cwd, path).lstrip("/")
try:
vfs, rem = self.hub.asrv.vfs.get(vpath, self.uname, True, False) vfs, rem = self.hub.asrv.vfs.get(vpath, self.uname, True, False)
fsroot, vfs_ls, vfs_virt = vfs.ls( fsroot, vfs_ls, vfs_virt = vfs.ls(
@ -141,9 +142,13 @@ class FtpFs(AbstractedFS):
vfs_ls.sort() vfs_ls.sort()
return vfs_ls return vfs_ls
except Exception as ex: except Exception as ex:
if vpath:
# display write-only folders as empty # display write-only folders as empty
return [] return []
# return list of volumes
return [x.split("/")[0] for x in self.hub.asrv.vfs.all_vols.keys()]
def rmdir(self, path): def rmdir(self, path):
ap = self.rv2a(path, d=True) ap = self.rv2a(path, d=True)
bos.rmdir(ap) bos.rmdir(ap)
@ -210,8 +215,11 @@ class FtpFs(AbstractedFS):
return bos.path.islink(ap) return bos.path.islink(ap)
def isdir(self, path): def isdir(self, path):
try:
st = self.stat(path) st = self.stat(path)
return stat.S_ISDIR(st.st_mode) return stat.S_ISDIR(st.st_mode)
except:
return True
def getsize(self, path): def getsize(self, path):
ap = self.rv2a(path) ap = self.rv2a(path)