diff --git a/bin/partyfuse.py b/bin/partyfuse.py index 9fa37cd5..da7ce54e 100755 --- a/bin/partyfuse.py +++ b/bin/partyfuse.py @@ -393,7 +393,8 @@ class Gateway(object): if r.status != 200: self.closeconn() info("http error %s reading dir %r", r.status, web_path) - raise FuseOSError(errno.ENOENT) + err = errno.ENOENT if r.status == 404 else errno.EIO + raise FuseOSError(err) ctype = r.getheader("Content-Type", "") if ctype == "application/json": diff --git a/bin/u2c.py b/bin/u2c.py index ef0f2fa9..977ccbda 100755 --- a/bin/u2c.py +++ b/bin/u2c.py @@ -1142,7 +1142,10 @@ class Ctl(object): if self.ar.drd: dp = os.path.join(top, rd) - lnodes = set(os.listdir(dp)) + try: + lnodes = set(os.listdir(dp)) + except: + lnodes = list(ls) # fs eio; don't delete if ptn: zs = dp.replace(sep, b"/").rstrip(b"/") + b"/" zls = [zs + x for x in lnodes] diff --git a/copyparty/authsrv.py b/copyparty/authsrv.py index 2fc613ca..c7114bac 100644 --- a/copyparty/authsrv.py +++ b/copyparty/authsrv.py @@ -591,10 +591,11 @@ class VFS(object): scandir: bool, permsets: list[list[bool]], lstat: bool = False, + throw: bool = False, ) -> tuple[str, list[tuple[str, os.stat_result]], dict[str, "VFS"]]: """replaces _ls for certain shares (single-file, or file selection)""" vn, rem = self.shr_src # type: ignore - abspath, real, _ = vn.ls(rem, "\n", scandir, permsets, lstat) + abspath, real, _ = vn.ls(rem, "\n", scandir, permsets, lstat, throw) real = [x for x in real if os.path.basename(x[0]) in self.shr_files] return abspath, real, {} @@ -605,11 +606,12 @@ class VFS(object): scandir: bool, permsets: list[list[bool]], lstat: bool = False, + throw: bool = False, ) -> tuple[str, list[tuple[str, os.stat_result]], dict[str, "VFS"]]: """return user-readable [fsdir,real,virt] items at vpath""" virt_vis = {} # nodes readable by user abspath = self.canonical(rem) - real = list(statdir(self.log, scandir, lstat, abspath)) + real = list(statdir(self.log, scandir, lstat, abspath, throw)) real.sort() if not rem: # no vfs nodes in the list of real inodes diff --git a/copyparty/ftpd.py b/copyparty/ftpd.py index 2cbe93a9..11e2f600 100644 --- a/copyparty/ftpd.py +++ b/copyparty/ftpd.py @@ -296,6 +296,7 @@ class FtpFs(AbstractedFS): self.uname, not self.args.no_scandir, [[True, False], [False, True]], + throw=True, ) vfs_ls = [x[0] for x in vfs_ls1] vfs_ls.extend(vfs_virt.keys()) diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 76d17bbb..808cb008 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -1450,6 +1450,7 @@ class HttpCli(object): not self.args.no_scandir, [[True, False]], lstat="davrt" not in vn.flags, + throw=True, ) if not self.can_read: vfs_ls = [] @@ -5459,6 +5460,7 @@ class HttpCli(object): not self.args.no_scandir, [[True, False], [False, True]], lstat="lt" in self.uparam, + throw=True, ) stats = {k: v for k, v in vfs_ls} ls_names = [x[0] for x in vfs_ls] diff --git a/copyparty/tftpd.py b/copyparty/tftpd.py index cd16681c..f2403fbe 100644 --- a/copyparty/tftpd.py +++ b/copyparty/tftpd.py @@ -269,6 +269,7 @@ class Tftpd(object): "*", not self.args.no_scandir, [[True, False]], + throw=True, ) dnames = set([x[0] for x in vfs_ls if stat.S_ISDIR(x[1].st_mode)]) dirs1 = [(v.st_mtime, v.st_size, k + "/") for k, v in vfs_ls if k in dnames] diff --git a/copyparty/th_srv.py b/copyparty/th_srv.py index 3c3ccd99..dd45596c 100644 --- a/copyparty/th_srv.py +++ b/copyparty/th_srv.py @@ -896,7 +896,9 @@ class ThumbSrv(object): prev_b64 = None prev_fp = "" try: - t1 = statdir(self.log_func, not self.args.no_scandir, False, thumbpath) + t1 = statdir( + self.log_func, not self.args.no_scandir, False, thumbpath, False + ) ents = sorted(list(t1)) except: return 0 diff --git a/copyparty/up2k.py b/copyparty/up2k.py index 47048b99..ced5062d 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -1347,7 +1347,7 @@ class Up2k(object): rds = rd + "/" if rd else "" cdirs = cdir + os.sep - g = statdir(self.log_func, not self.args.no_scandir, True, cdir) + g = statdir(self.log_func, not self.args.no_scandir, True, cdir, False) gl = sorted(g) partials = set([x[0] for x in gl if "PARTIAL" in x[0]]) for iname, inf in gl: diff --git a/copyparty/util.py b/copyparty/util.py index a22abf90..1fe1a708 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -2862,7 +2862,7 @@ def sendfile_kern( def statdir( - logger: Optional["RootLogger"], scandir: bool, lstat: bool, top: str + logger: Optional["RootLogger"], scandir: bool, lstat: bool, top: str, throw: bool ) -> Generator[tuple[str, os.stat_result], None, None]: if lstat and ANYWIN: lstat = False @@ -2898,6 +2898,12 @@ def statdir( logger(src, "[s] {} @ {}".format(repr(ex), fsdec(abspath)), 6) except Exception as ex: + if throw: + zi = getattr(ex, "errno", 0) + if zi == errno.ENOENT: + raise Pebkac(404, str(ex)) + raise + t = "{} @ {}".format(repr(ex), top) if logger: logger(src, t, 1) @@ -2906,7 +2912,7 @@ def statdir( def dir_is_empty(logger: "RootLogger", scandir: bool, top: str): - for _ in statdir(logger, scandir, False, top): + for _ in statdir(logger, scandir, False, top, False): return False return True @@ -2919,7 +2925,7 @@ def rmdirs( top = os.path.dirname(top) depth -= 1 - stats = statdir(logger, scandir, lstat, top) + stats = statdir(logger, scandir, lstat, top, False) dirs = [x[0] for x in stats if stat.S_ISDIR(x[1].st_mode)] dirs = [os.path.join(top, x) for x in dirs] ok = []