Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
feb1acd43a | ||
|
|
a9591db734 | ||
|
|
9ebf148cbe | ||
|
|
a473e5e19a | ||
|
|
5d3034c231 | ||
|
|
c3a895af64 |
@@ -481,7 +481,6 @@ def run_argparse(argv: list[str], formatter: Any) -> argparse.Namespace:
|
||||
ap2.add_argument("--hardlink", action="store_true", help="prefer hardlinks instead of symlinks when possible (within same filesystem)")
|
||||
ap2.add_argument("--never-symlink", action="store_true", help="do not fallback to symlinks when a hardlink cannot be made")
|
||||
ap2.add_argument("--no-dedup", action="store_true", help="disable symlink/hardlink creation; copy file contents instead")
|
||||
ap2.add_argument("--thickfs", metavar="REGEX", type=u, default="fat|vfat|ex.?fat|hpfs|fuse", help="filesystems which dont support sparse files")
|
||||
ap2.add_argument("--sparse", metavar="MiB", type=int, default=4, help="windows-only: minimum size of incoming uploads through up2k before they are made into sparse files")
|
||||
ap2.add_argument("--turbo", metavar="LVL", type=int, default=0, help="configure turbo-mode in up2k client; 0 = off and warn if enabled, 1 = off, 2 = on, 3 = on and disable datecheck")
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# coding: utf-8
|
||||
|
||||
VERSION = (1, 3, 2)
|
||||
VERSION = (1, 3, 3)
|
||||
CODENAME = "god dag"
|
||||
BUILD_DT = (2022, 6, 20)
|
||||
BUILD_DT = (2022, 6, 27)
|
||||
|
||||
S_VERSION = ".".join(map(str, VERSION))
|
||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
|
||||
|
||||
@@ -10,7 +10,7 @@ from .authsrv import AXS, VFS
|
||||
from .util import chkcmd, min_ex
|
||||
|
||||
try:
|
||||
from typing import Optional, Union
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from .util import RootLogger
|
||||
except:
|
||||
@@ -28,8 +28,8 @@ class Fstab(object):
|
||||
def log(self, msg: str, c: Union[int, str] = 0) -> None:
|
||||
self.log_func("fstab", msg + "\033[K", c)
|
||||
|
||||
def get(self, path: str):
|
||||
if time.time() - self.age > 600 or len(self.cache) > 9000:
|
||||
def get(self, path: str) -> str:
|
||||
if len(self.cache) > 9000:
|
||||
self.age = time.time()
|
||||
self.tab = None
|
||||
self.cache = {}
|
||||
@@ -64,7 +64,7 @@ class Fstab(object):
|
||||
self.log("found {} at {}".format(fs, path))
|
||||
return fs
|
||||
|
||||
def build_tab(self):
|
||||
def build_tab(self) -> None:
|
||||
self.log("building tab")
|
||||
|
||||
sptn = r"^.*? on (.*) type ([^ ]+) \(.*"
|
||||
@@ -79,7 +79,8 @@ class Fstab(object):
|
||||
if not m:
|
||||
continue
|
||||
|
||||
tab1.append(m.groups())
|
||||
zs1, zs2 = m.groups()
|
||||
tab1.append((str(zs1), str(zs2)))
|
||||
|
||||
tab1.sort(key=lambda x: (len(x[0]), x[0]))
|
||||
path1, fs1 = tab1[0]
|
||||
@@ -89,18 +90,30 @@ class Fstab(object):
|
||||
|
||||
self.tab = tab
|
||||
|
||||
def get_unix(self, path: str):
|
||||
def relabel(self, path: str, nval: str) -> None:
|
||||
assert self.tab
|
||||
ptn = re.compile(r"^[^\\/]*")
|
||||
vn, _ = self.tab._find(path)
|
||||
visit = [vn]
|
||||
while visit:
|
||||
vn = visit.pop()
|
||||
vn.realpath = ptn.sub(nval, vn.realpath)
|
||||
visit.extend(list(vn.nodes.values()))
|
||||
self.cache = {}
|
||||
|
||||
def get_unix(self, path: str) -> str:
|
||||
if not self.tab:
|
||||
self.build_tab()
|
||||
|
||||
assert self.tab
|
||||
return self.tab._find(path)[0].realpath.split("/")[0]
|
||||
|
||||
def get_w32(self, path: str):
|
||||
def get_w32(self, path: str) -> str:
|
||||
# list mountpoints: fsutil fsinfo drives
|
||||
|
||||
from ctypes.wintypes import BOOL, DWORD, LPCWSTR, LPDWORD, LPWSTR, MAX_PATH
|
||||
|
||||
def echk(rc, fun, args):
|
||||
def echk(rc: int, fun: Any, args: Any) -> None:
|
||||
if not rc:
|
||||
raise ctypes.WinError(ctypes.get_last_error())
|
||||
return None
|
||||
|
||||
@@ -2403,6 +2403,16 @@ class HttpCli(object):
|
||||
"themes": self.args.themes,
|
||||
"turbolvl": self.args.turbo,
|
||||
}
|
||||
|
||||
if self.args.js_browser:
|
||||
j2a["js"] = self.args.js_browser
|
||||
|
||||
if self.args.css_browser:
|
||||
j2a["css"] = self.args.css_browser
|
||||
|
||||
if not self.conn.hsrv.prism:
|
||||
j2a["no_prism"] = True
|
||||
|
||||
if not self.can_read:
|
||||
if is_ls:
|
||||
return self.tx_ls(ls_ret)
|
||||
@@ -2602,9 +2612,6 @@ class HttpCli(object):
|
||||
if doctxt is not None:
|
||||
j2a["doc"] = doctxt
|
||||
|
||||
if not self.conn.hsrv.prism:
|
||||
j2a["no_prism"] = True
|
||||
|
||||
for d in dirs:
|
||||
d["name"] += "/"
|
||||
|
||||
@@ -2616,19 +2623,12 @@ class HttpCli(object):
|
||||
else:
|
||||
j2a["files"] = dirs + files
|
||||
|
||||
j2a["logues"] = logues
|
||||
j2a["taglist"] = taglist
|
||||
j2a["txt_ext"] = self.args.textfiles.replace(",", " ")
|
||||
|
||||
if "mth" in vn.flags:
|
||||
j2a["def_hcols"] = vn.flags["mth"].split(",")
|
||||
|
||||
if self.args.js_browser:
|
||||
j2a["js"] = self.args.js_browser
|
||||
|
||||
if self.args.css_browser:
|
||||
j2a["css"] = self.args.css_browser
|
||||
|
||||
html = self.j2s(tpl, **j2a)
|
||||
self.reply(html.encode("utf-8", "replace"))
|
||||
return True
|
||||
|
||||
@@ -132,7 +132,6 @@ class Up2k(object):
|
||||
thr.start()
|
||||
|
||||
self.fstab = Fstab(self.log_func)
|
||||
self.no_sparse = re.compile(self.args.thickfs)
|
||||
|
||||
if self.args.no_fastboot:
|
||||
self.deferred_init()
|
||||
@@ -1327,7 +1326,7 @@ class Up2k(object):
|
||||
|
||||
# check if filesystem supports sparse files;
|
||||
# refuse out-of-order / multithreaded uploading if sprs False
|
||||
sprs = not self.no_sparse.match(self.fstab.get(pdir))
|
||||
sprs = self.fstab.get(pdir) != "ng"
|
||||
|
||||
with self.mutex:
|
||||
cur = self.cur.get(cj["ptop"])
|
||||
@@ -2214,31 +2213,49 @@ class Up2k(object):
|
||||
|
||||
dip = job["addr"].replace(":", ".")
|
||||
suffix = "-{:.6f}-{}".format(job["t0"], dip)
|
||||
t0 = time.time()
|
||||
with ren_open(tnam, "wb", fdir=pdir, suffix=suffix) as zfw:
|
||||
f, job["tnam"] = zfw["orz"]
|
||||
abspath = os.path.join(pdir, job["tnam"])
|
||||
sprs = job["sprs"]
|
||||
sz = job["size"]
|
||||
relabel = False
|
||||
if (
|
||||
ANYWIN
|
||||
and job["sprs"]
|
||||
and sprs
|
||||
and self.args.sparse
|
||||
and self.args.sparse * 1024 * 1024 <= job["size"]
|
||||
and self.args.sparse * 1024 * 1024 <= sz
|
||||
):
|
||||
fp = os.path.join(pdir, job["tnam"])
|
||||
try:
|
||||
sp.check_call(["fsutil", "sparse", "setflag", fp])
|
||||
sp.check_call(["fsutil", "sparse", "setflag", abspath])
|
||||
except:
|
||||
self.log("could not sparse [{}]".format(fp), 3)
|
||||
self.log("could not sparse [{}]".format(abspath), 3)
|
||||
relabel = True
|
||||
sprs = False
|
||||
|
||||
if job["hash"] and job["sprs"]:
|
||||
f.seek(job["size"] - 1)
|
||||
if not ANYWIN and sprs and sz > 1024 * 1024:
|
||||
fs = self.fstab.get(pdir)
|
||||
if fs != "ok":
|
||||
relabel = True
|
||||
f.seek(1024 * 1024 - 1)
|
||||
f.write(b"e")
|
||||
f.flush()
|
||||
try:
|
||||
nblk = bos.stat(abspath).st_blocks
|
||||
sprs = nblk < 2048
|
||||
except:
|
||||
sprs = False
|
||||
|
||||
if relabel:
|
||||
t = "sparse files {} on {} filesystem at {}"
|
||||
nv = "ok" if sprs else "ng"
|
||||
self.log(t.format(nv, self.fstab.get(pdir), pdir))
|
||||
self.fstab.relabel(pdir, nv)
|
||||
job["sprs"] = sprs
|
||||
|
||||
if job["hash"] and sprs:
|
||||
f.seek(sz - 1)
|
||||
f.write(b"e")
|
||||
|
||||
td = time.time() - t0
|
||||
if td > 3 and not ANYWIN:
|
||||
t = "WARNING: filesystem [{}] at [{}] probably does support sparse files; adjust the list in --thickfs and maybe create a github issue (please mention the filesystem + any related info about your setup if you do)"
|
||||
fs = self.fstab.get(pdir)
|
||||
self.log(t.format(fs, pdir), 1)
|
||||
|
||||
if not job["hash"]:
|
||||
self._finish_upload(job["ptop"], job["wark"])
|
||||
|
||||
|
||||
@@ -589,6 +589,7 @@ def ren_open(
|
||||
ext = bname[ofs:] + ext
|
||||
bname = bname[:ofs]
|
||||
|
||||
asciified = False
|
||||
b64 = ""
|
||||
while True:
|
||||
try:
|
||||
@@ -614,11 +615,20 @@ def ren_open(
|
||||
|
||||
except OSError as ex_:
|
||||
ex = ex_
|
||||
|
||||
if ex.errno == 22 and not asciified:
|
||||
asciified = True
|
||||
bname, fname = [
|
||||
zs.encode("ascii", "replace").decode("ascii").replace("?", "_")
|
||||
for zs in [bname, fname]
|
||||
]
|
||||
continue
|
||||
|
||||
if ex.errno not in [36, 63] and (not WINDOWS or ex.errno != 22):
|
||||
raise
|
||||
|
||||
if not b64:
|
||||
zs = (bname + ext).encode("utf-8", "replace")
|
||||
zs = (orig_name + "\n" + suffix).encode("utf-8", "replace")
|
||||
zs = hashlib.sha512(zs).digest()[:12]
|
||||
b64 = base64.urlsafe_b64encode(zs).decode("utf-8")
|
||||
|
||||
@@ -1695,16 +1705,16 @@ def termsize() -> tuple[int, int]:
|
||||
# from hashwalk
|
||||
env = os.environ
|
||||
|
||||
def ioctl_GWINSZ(fd):
|
||||
def ioctl_GWINSZ(fd: int) -> Optional[tuple[int, int]]:
|
||||
try:
|
||||
import fcntl
|
||||
import struct
|
||||
import termios
|
||||
|
||||
cr = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234"))
|
||||
cr = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, b"1234"))
|
||||
return int(cr[1]), int(cr[0])
|
||||
except:
|
||||
return
|
||||
return cr
|
||||
return None
|
||||
|
||||
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
|
||||
if not cr:
|
||||
@@ -1715,13 +1725,13 @@ def termsize() -> tuple[int, int]:
|
||||
except:
|
||||
pass
|
||||
|
||||
if not cr:
|
||||
try:
|
||||
cr = (env["LINES"], env["COLUMNS"])
|
||||
except:
|
||||
cr = (25, 80)
|
||||
if cr:
|
||||
return cr
|
||||
|
||||
return int(cr[1]), int(cr[0])
|
||||
try:
|
||||
return int(env["COLUMNS"]), int(env["LINES"])
|
||||
except:
|
||||
return 80, 25
|
||||
|
||||
|
||||
class Pebkac(Exception):
|
||||
|
||||
Reference in New Issue
Block a user