diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index fb21a1eb..82bc533f 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -5,6 +5,7 @@ import argparse # typechk import base64 import calendar import copy +import errno import gzip import itertools import json @@ -1290,10 +1291,10 @@ class HttpCli(object): except OSError as ex: self.log("makedirs failed [{}]".format(dst)) if not bos.path.isdir(dst): - if ex.errno == 13: + if ex.errno == errno.EACCES: raise Pebkac(500, "the server OS denied write-access") - if ex.errno == 17: + if ex.errno == errno.EEXIST: raise Pebkac(400, "some file got your folder name") raise Pebkac(500, min_ex()) @@ -1544,7 +1545,7 @@ class HttpCli(object): try: bos.mkdir(fn) except OSError as ex: - if ex.errno == 13: + if ex.errno == errno.EACCES: raise Pebkac(500, "the server OS denied write-access") raise Pebkac(500, "mkdir failed:\n" + min_ex()) @@ -1862,7 +1863,7 @@ class HttpCli(object): srv_lastmod = st.st_mtime srv_lastmod3 = int(srv_lastmod * 1000) except OSError as ex: - if ex.errno != 2: + if ex.errno != errno.ENOENT: raise # if file exists, chekc that timestamp matches the client's diff --git a/copyparty/httpsrv.py b/copyparty/httpsrv.py index b13bc2e7..ff0ce449 100644 --- a/copyparty/httpsrv.py +++ b/copyparty/httpsrv.py @@ -35,6 +35,7 @@ from .util import ( FHC, Garda, Magician, + E_SCK, min_ex, shut_socket, spack, @@ -332,7 +333,7 @@ class HttpSrv(object): cli.run() except (OSError, socket.error) as ex: - if ex.errno not in [10038, 10054, 107, 57, 49, 9]: + if ex.errno not in E_SCK: self.log( "%s %s" % addr, "run({}): {}".format(fno, ex), @@ -354,13 +355,7 @@ class HttpSrv(object): "shut({}): {}".format(fno, ex), c="1;30", ) - if ex.errno not in [10038, 10054, 107, 57, 49, 9]: - # 10038 No longer considered a socket - # 10054 Foribly closed by remote - # 107 Transport endpoint not connected - # 57 Socket is not connected - # 49 Can't assign requested address (wifi down) - # 9 Bad file descriptor + if ex.errno not in E_SCK: raise finally: with self.mutex: diff --git a/copyparty/tcpsrv.py b/copyparty/tcpsrv.py index d20e02ff..bf60afe8 100644 --- a/copyparty/tcpsrv.py +++ b/copyparty/tcpsrv.py @@ -8,7 +8,15 @@ import sys from .__init__ import ANYWIN, MACOS, PY2, TYPE_CHECKING, VT100, unicode from .stolen.qrcodegen import QrCode -from .util import chkcmd, sunpack, termsize +from .util import ( + E_ACCESS, + E_ADDR_IN_USE, + E_ADDR_NOT_AVAIL, + E_UNREACH, + chkcmd, + sunpack, + termsize, +) if TYPE_CHECKING: from .svchub import SvcHub @@ -133,9 +141,9 @@ class TcpSrv(object): srv.bind((ip, port)) self.srv.append(srv) except (OSError, socket.error) as ex: - if ex.errno in [98, 48]: + if ex.errno in E_ADDR_IN_USE: e = "\033[1;31mport {} is busy on interface {}\033[0m".format(port, ip) - elif ex.errno in [99, 49]: + elif ex.errno in E_ADDR_NOT_AVAIL: e = "\033[1;31minterface {} does not exist\033[0m".format(ip) else: raise @@ -321,9 +329,9 @@ class TcpSrv(object): default_route = s.getsockname()[0] break except (OSError, socket.error) as ex: - if ex.errno == 13: + if ex.errno in E_ACCESS: self.log("tcpsrv", "eaccess {} (trying next)".format(ip)) - elif ex.errno not in [101, 10065, 10051]: + elif ex.errno not in E_UNREACH: self.log("tcpsrv", "route lookup failed; err {}".format(ex.errno)) s.close() diff --git a/copyparty/up2k.py b/copyparty/up2k.py index 40725cf3..fd7ac1cc 100644 --- a/copyparty/up2k.py +++ b/copyparty/up2k.py @@ -2,6 +2,7 @@ from __future__ import print_function, unicode_literals import base64 +import errno import gzip import hashlib import json @@ -2670,7 +2671,7 @@ class Up2k(object): try: atomic_move(sabs, dabs) except OSError as ex: - if ex.errno != 18: + if ex.errno != errno.EXDEV: raise self.log("cross-device move:\n {}\n {}".format(sabs, dabs)) diff --git a/copyparty/util.py b/copyparty/util.py index d731dbcc..5d8be452 100644 --- a/copyparty/util.py +++ b/copyparty/util.py @@ -3,6 +3,7 @@ from __future__ import print_function, unicode_literals import base64 import contextlib +import errno import hashlib import hmac import math @@ -29,6 +30,28 @@ from .__init__ import ANYWIN, MACOS, PY2, TYPE_CHECKING, VT100, WINDOWS from .__version__ import S_BUILD_DT, S_VERSION from .stolen import surrogateescape + +def _ens(want: str) -> tuple[int, ...]: + ret: list[int] = [] + for v in want.split(): + try: + ret.append(getattr(errno, v)) + except: + pass + + return tuple(ret) + + +# WSAECONNRESET - foribly closed by remote +# WSAENOTSOCK - no longer a socket +# EUNATCH - can't assign requested address (wifi down) +E_SCK = _ens("ENOTCONN EUNATCH EBADF WSAENOTSOCK WSAECONNRESET") +E_ADDR_NOT_AVAIL = _ens("EADDRNOTAVAIL WSAEADDRNOTAVAIL") +E_ADDR_IN_USE = _ens("EADDRINUSE WSAEADDRINUSE") +E_ACCESS = _ens("EACCES WSAEACCES") +E_UNREACH = _ens("EHOSTUNREACH WSAEHOSTUNREACH ENETUNREACH WSAENETUNREACH") + + try: import ctypes import fcntl @@ -1020,7 +1043,7 @@ def ren_open( except OSError as ex_: ex = ex_ - if ex.errno == 22 and not asciified: + if ex.errno == errno.EINVAL and not asciified: asciified = True bname, fname = [ zs.encode("ascii", "replace").decode("ascii").replace("?", "_") @@ -1028,7 +1051,10 @@ def ren_open( ] continue - if ex.errno not in [36, 63, 95] and (not WINDOWS or ex.errno != 22): + # ENOTSUP: zfs on ubuntu 20.04 + if ex.errno not in (errno.ENAMETOOLONG, errno.ENOSR, errno.ENOTSUP) and ( + not WINDOWS or ex.errno != errno.EINVAL + ): raise if not b64: @@ -1884,8 +1910,8 @@ def sendfile_kern( stuck = 0 except OSError as ex: d = time.time() - stuck - log("sendfile stuck for {:.3f} sec: {!r}".format(d, ex)) - if d < 3600 and ex.errno == 11: # eagain + log("sendfile stuck for {:.3f} sec: {!r}".format(d, ex), "90") + if d < 3600 and ex.errno == errno.EWOULDBLOCK: continue n = 0