diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 02f9efe6..76df3e2c 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1478,6 +1478,7 @@ def add_debug(ap): ap2.add_argument("--bak-flips", action="store_true", help="[up2k] if a client uploads a bitflipped/corrupted chunk, store a copy according to \033[33m--bf-nc\033[0m and \033[33m--bf-dir\033[0m") ap2.add_argument("--bf-nc", metavar="NUM", type=int, default=200, help="bak-flips: stop if there's more than \033[33mNUM\033[0m files at \033[33m--kf-dir\033[0m already; default: 6.3 GiB max (200*32M)") ap2.add_argument("--bf-dir", metavar="PATH", type=u, default="bf", help="bak-flips: store corrupted chunks at \033[33mPATH\033[0m; default: folder named 'bf' wherever copyparty was started") + ap2.add_argument("--bf-log", metavar="PATH", type=u, default="", help="bak-flips: log corruption info to a textfile at \033[33mPATH\033[0m") # fmt: on diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 772e593f..1a5f9ad6 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -2036,13 +2036,32 @@ class HttpCli(object): return True def bakflip( - self, f: typing.BinaryIO, ofs: int, sz: int, sha: str, flags: dict[str, Any] + self, + f: typing.BinaryIO, + ap: str, + ofs: int, + sz: int, + good_sha: str, + bad_sha: str, + flags: dict[str, Any], ) -> None: + now = time.time() + t = "bad-chunk: %.3f %s %s %d %s %s %s" + t = t % (now, bad_sha, good_sha, ofs, self.ip, self.uname, ap) + self.log(t, 5) + + if self.args.bf_log: + try: + with open(self.args.bf_log, "ab+") as f2: + f2.write((t + "\n").encode("utf-8", "replace")) + except Exception as ex: + self.log("append %s failed: %r" % (self.args.bf_log, ex)) + if not self.args.bak_flips or self.args.nw: return sdir = self.args.bf_dir - fp = os.path.join(sdir, sha) + fp = os.path.join(sdir, bad_sha) if bos.path.exists(fp): return self.log("no bakflip; have it", 6) @@ -2371,7 +2390,9 @@ class HttpCli(object): if sha_b64 != chash: try: - self.bakflip(f, cstart[0], post_sz, sha_b64, vfs.flags) + self.bakflip( + f, path, cstart[0], post_sz, chash, sha_b64, vfs.flags + ) except: self.log("bakflip failed: " + min_ex())