From bb715704b7eec2a6cbff2d76fcc01f35f3824230 Mon Sep 17 00:00:00 2001 From: ed Date: Sun, 15 Sep 2024 14:39:35 +0000 Subject: [PATCH] `ren_open` was too fancy --- copyparty/httpcli.py | 20 ++++++++++++-------- copyparty/up2k.py | 11 +++++++---- copyparty/util.py | 29 +++++++++++++---------------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 72edcd9e..c2097fd5 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -1865,10 +1865,12 @@ class HttpCli(object): # small toctou, but better than clobbering a hardlink wunlink(self.log, path, vfs.flags) - with ren_open(fn, *open_a, **params) as zfw: - f, fn = zfw["orz"] + f, fn = ren_open(fn, *open_a, **params) + try: path = os.path.join(fdir, fn) post_sz, sha_hex, sha_b64 = hashcopy(reader, f, self.args.s_wr_slp) + finally: + f.close() if lim: lim.nup(self.ip) @@ -1907,8 +1909,8 @@ class HttpCli(object): fn2 = fn.rsplit(".", 1)[0] + "." + ext params["suffix"] = suffix[:-4] - with ren_open(fn, *open_a, **params) as zfw: - f, fn = zfw["orz"] + f, fn2 = ren_open(fn2, *open_a, **params) + f.close() path2 = os.path.join(fdir, fn2) atomic_move(self.log, path, path2, vfs.flags) @@ -2741,8 +2743,8 @@ class HttpCli(object): bos.makedirs(fdir) # reserve destination filename - with ren_open(fname, "wb", fdir=fdir, suffix=suffix) as zfw: - fname = zfw["orz"][1] + f, fname = ren_open(fname, "wb", fdir=fdir, suffix=suffix) + f.close() tnam = fname + ".PARTIAL" if self.args.dotpart: @@ -2765,8 +2767,8 @@ class HttpCli(object): v2 = lim.dfv - lim.dfl max_sz = min(v1, v2) if v1 and v2 else v1 or v2 - with ren_open(tnam, "wb", self.args.iobuf, **open_args) as zfw: - f, tnam = zfw["orz"] + f, tnam = ren_open(tnam, "wb", self.args.iobuf, **open_args) + try: tabspath = os.path.join(fdir, tnam) self.log("writing to {}".format(tabspath)) sz, sha_hex, sha_b64 = hashcopy( @@ -2774,6 +2776,8 @@ class HttpCli(object): ) if sz == 0: raise Pebkac(400, "empty files in post") + finally: + f.close() if lim: lim.nup(self.ip) diff --git a/copyparty/up2k.py b/copyparty/up2k.py index bf171a5e..62d5183f 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -3186,8 +3186,9 @@ class Up2k(object): dip = self.hub.iphash.s(ip) suffix = "-%.6f-%s" % (ts, dip) - with ren_open(fname, "wb", fdir=fdir, suffix=suffix) as zfw: - return zfw["orz"][1] + f, ret = ren_open(fname, "wb", fdir=fdir, suffix=suffix) + f.close() + return ret def _symlink( self, @@ -4530,8 +4531,8 @@ class Up2k(object): dip = self.hub.iphash.s(job["addr"]) suffix = "-%.6f-%s" % (job["t0"], dip) - with ren_open(tnam, "wb", fdir=pdir, suffix=suffix) as zfw: - f, job["tnam"] = zfw["orz"] + f, job["tnam"] = ren_open(tnam, "wb", fdir=pdir, suffix=suffix) + try: abspath = djoin(pdir, job["tnam"]) sprs = job["sprs"] sz = job["size"] @@ -4578,6 +4579,8 @@ class Up2k(object): if job["hash"] and sprs: f.seek(sz - 1) f.write(b"e") + finally: + f.close() if not job["hash"]: self._finish_upload(job["ptop"], job["wark"]) diff --git a/copyparty/util.py b/copyparty/util.py index a7d1ad53..7a060bea 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -1385,18 +1385,13 @@ def min_ex(max_lines: int = 8, reverse: bool = False) -> str: return "\n".join(ex[-max_lines:][:: -1 if reverse else 1]) -@contextlib.contextmanager -def ren_open( - fname: str, *args: Any, **kwargs: Any -) -> Generator[dict[str, tuple[typing.IO[Any], str]], None, None]: +def ren_open(fname: str, *args: Any, **kwargs: Any) -> tuple[typing.IO[Any], str]: fun = kwargs.pop("fun", open) fdir = kwargs.pop("fdir", None) suffix = kwargs.pop("suffix", None) if fname == os.devnull: - with fun(fname, *args, **kwargs) as f: - yield {"orz": (f, fname)} - return + return fun(fname, *args, **kwargs), fname if suffix: ext = fname.split(".")[-1] @@ -1418,6 +1413,7 @@ def ren_open( asciified = False b64 = "" while True: + f = None try: if fdir: fpath = os.path.join(fdir, fname) @@ -1429,19 +1425,20 @@ def ren_open( fname += suffix ext += suffix - with fun(fsenc(fpath), *args, **kwargs) as f: - if b64: - assert fdir # !rm - fp2 = "fn-trunc.%s.txt" % (b64,) - fp2 = os.path.join(fdir, fp2) - with open(fsenc(fp2), "wb") as f2: - f2.write(orig_name.encode("utf-8")) + f = fun(fsenc(fpath), *args, **kwargs) + if b64: + assert fdir # !rm + fp2 = "fn-trunc.%s.txt" % (b64,) + fp2 = os.path.join(fdir, fp2) + with open(fsenc(fp2), "wb") as f2: + f2.write(orig_name.encode("utf-8")) - yield {"orz": (f, fname)} - return + return f, fname except OSError as ex_: ex = ex_ + if f: + f.close() # EPERM: android13 if ex.errno in (errno.EINVAL, errno.EPERM) and not asciified: