centralize mojibake support stuff

This commit is contained in:
ed 2021-07-24 21:56:55 +02:00
parent 4451485664
commit d020527c6f
14 changed files with 176 additions and 83 deletions

View file

@ -11,6 +11,7 @@ import threading
from .__init__ import WINDOWS from .__init__ import WINDOWS
from .util import IMPLICATIONS, uncyg, undot, absreal, Pebkac, fsdec, fsenc, statdir from .util import IMPLICATIONS, uncyg, undot, absreal, Pebkac, fsdec, fsenc, statdir
from .bos import bos
class AXS(object): class AXS(object):
@ -555,7 +556,7 @@ class AuthSrv(object):
for nch in range(len(hid)): for nch in range(len(hid)):
hpath = os.path.join(self.args.hist, hid[: nch + 1]) hpath = os.path.join(self.args.hist, hid[: nch + 1])
try: try:
os.makedirs(hpath) bos.makedirs(hpath)
except: except:
pass pass
@ -579,7 +580,7 @@ class AuthSrv(object):
vol.histpath = absreal(vol.histpath) vol.histpath = absreal(vol.histpath)
if vol.dbv: if vol.dbv:
if os.path.exists(os.path.join(vol.histpath, "up2k.db")): if bos.path.exists(os.path.join(vol.histpath, "up2k.db")):
promote.append(vol) promote.append(vol)
vol.dbv = None vol.dbv = None
else: else:

View file

54
copyparty/bos/bos.py Normal file
View file

@ -0,0 +1,54 @@
# coding: utf-8
from __future__ import print_function, unicode_literals
import os
from ..util import fsenc, fsdec
from . import path
# grep -hRiE '(^|[^a-zA-Z_\.-])os\.' . | gsed -r 's/ /\n/g;s/\(/(\n/g' | grep -hRiE '(^|[^a-zA-Z_\.-])os\.' | sort | uniq -c
# printf 'os\.(%s)' "$(grep ^def bos/__init__.py | gsed -r 's/^def //;s/\(.*//' | tr '\n' '|' | gsed -r 's/.$//')"
def chmod(p, mode, follow_symlinks=True):
return os.chmod(fsenc(p), mode, follow_symlinks=follow_symlinks)
def listdir(p="."):
return [fsdec(x) for x in os.listdir(fsenc(p))]
def lstat(p):
return os.lstat(fsenc(p))
def makedirs(name, mode=0o755, exist_ok=None):
return os.makedirs(fsenc(name), mode=mode, exist_ok=exist_ok)
def mkdir(p, mode=0o755):
return os.mkdir(fsenc(p), mode=mode)
def rename(src, dst):
return os.rename(fsenc(src), fsenc(dst))
def replace(src, dst):
return os.replace(fsenc(src), fsenc(dst))
def rmdir(p):
return os.rmdir(fsenc(p))
def stat(p, follow_symlinks=True):
return os.stat(fsenc(p), follow_symlinks=follow_symlinks)
def unlink(p):
return os.unlink(fsenc(p))
def utime(p, times=None, follow_symlinks=True):
return os.utime(fsenc(p), times, follow_symlinks=follow_symlinks)

29
copyparty/bos/path.py Normal file
View file

@ -0,0 +1,29 @@
# coding: utf-8
from __future__ import print_function, unicode_literals
import os
from ..util import fsenc, fsdec
def exists(p):
return os.path.exists(fsenc(p))
def getmtime(p):
return os.path.getmtime(fsenc(p))
def getsize(p):
return os.path.getsize(fsenc(p))
def isdir(p):
return os.path.isdir(fsenc(p))
def islink(p):
return os.path.islink(fsenc(p))
def realpath(p):
return fsdec(os.path.realpath(fsenc(p)))

View file

@ -15,6 +15,7 @@ import calendar
from .__init__ import E, PY2, WINDOWS, ANYWIN, unicode from .__init__ import E, PY2, WINDOWS, ANYWIN, unicode
from .util import * # noqa # pylint: disable=unused-wildcard-import from .util import * # noqa # pylint: disable=unused-wildcard-import
from .bos import bos
from .authsrv import AuthSrv from .authsrv import AuthSrv
from .szip import StreamZip from .szip import StreamZip
from .star import StreamTar from .star import StreamTar
@ -615,11 +616,11 @@ class HttpCli(object):
if sub: if sub:
try: try:
dst = os.path.join(vfs.realpath, rem) dst = os.path.join(vfs.realpath, rem)
if not os.path.isdir(fsenc(dst)): if not bos.path.isdir(dst):
os.makedirs(fsenc(dst)) bos.makedirs(dst)
except OSError as ex: except OSError as ex:
self.log("makedirs failed [{}]".format(dst)) self.log("makedirs failed [{}]".format(dst))
if not os.path.isdir(fsenc(dst)): if not bos.path.isdir(dst):
if ex.errno == 13: if ex.errno == 13:
raise Pebkac(500, "the server OS denied write-access") raise Pebkac(500, "the server OS denied write-access")
@ -765,7 +766,7 @@ class HttpCli(object):
times = (int(time.time()), int(lastmod)) times = (int(time.time()), int(lastmod))
self.log("no more chunks, setting times {}".format(times)) self.log("no more chunks, setting times {}".format(times))
try: try:
os.utime(fsenc(path), times) bos.utime(path, times)
except: except:
self.log("failed to utime ({}, {})".format(path, times)) self.log("failed to utime ({}, {})".format(path, times))
@ -810,14 +811,14 @@ class HttpCli(object):
fdir = os.path.join(vfs.realpath, rem) fdir = os.path.join(vfs.realpath, rem)
fn = os.path.join(fdir, sanitized) fn = os.path.join(fdir, sanitized)
if not os.path.isdir(fsenc(fdir)): if not bos.path.isdir(fdir):
raise Pebkac(500, "parent folder does not exist") raise Pebkac(500, "parent folder does not exist")
if os.path.isdir(fsenc(fn)): if bos.path.isdir(fn):
raise Pebkac(500, "that folder exists already") raise Pebkac(500, "that folder exists already")
try: try:
os.mkdir(fsenc(fn)) bos.mkdir(fn)
except OSError as ex: except OSError as ex:
if ex.errno == 13: if ex.errno == 13:
raise Pebkac(500, "the server OS denied write-access") raise Pebkac(500, "the server OS denied write-access")
@ -847,7 +848,7 @@ class HttpCli(object):
fdir = os.path.join(vfs.realpath, rem) fdir = os.path.join(vfs.realpath, rem)
fn = os.path.join(fdir, sanitized) fn = os.path.join(fdir, sanitized)
if os.path.exists(fsenc(fn)): if bos.path.exists(fn):
raise Pebkac(500, "that file exists already") raise Pebkac(500, "that file exists already")
with open(fsenc(fn), "wb") as f: with open(fsenc(fn), "wb") as f:
@ -877,7 +878,7 @@ class HttpCli(object):
p_file, "", [".prologue.html", ".epilogue.html"] p_file, "", [".prologue.html", ".epilogue.html"]
) )
if not os.path.isdir(fsenc(fdir)): if not bos.path.isdir(fdir):
raise Pebkac(404, "that folder does not exist") raise Pebkac(404, "that folder does not exist")
suffix = ".{:.6f}-{}".format(time.time(), self.ip) suffix = ".{:.6f}-{}".format(time.time(), self.ip)
@ -916,10 +917,10 @@ class HttpCli(object):
suffix = ".PARTIAL" suffix = ".PARTIAL"
try: try:
os.rename(fsenc(fp), fsenc(fp2 + suffix)) bos.rename(fp, fp2 + suffix)
except: except:
fp2 = fp2[: -len(suffix) - 1] fp2 = fp2[: -len(suffix) - 1]
os.rename(fsenc(fp), fsenc(fp2 + suffix)) bos.rename(fp, fp2 + suffix)
raise raise
@ -1017,7 +1018,7 @@ class HttpCli(object):
fp = os.path.join(vfs.realpath, rem) fp = os.path.join(vfs.realpath, rem)
srv_lastmod = srv_lastmod3 = -1 srv_lastmod = srv_lastmod3 = -1
try: try:
st = os.stat(fsenc(fp)) st = bos.stat(fp)
srv_lastmod = st.st_mtime srv_lastmod = st.st_mtime
srv_lastmod3 = int(srv_lastmod * 1000) srv_lastmod3 = int(srv_lastmod * 1000)
except OSError as ex: except OSError as ex:
@ -1056,10 +1057,10 @@ class HttpCli(object):
mdir, mfile = os.path.split(fp) mdir, mfile = os.path.split(fp)
mfile2 = "{}.{:.3f}.md".format(mfile[:-3], srv_lastmod) mfile2 = "{}.{:.3f}.md".format(mfile[:-3], srv_lastmod)
try: try:
os.mkdir(fsenc(os.path.join(mdir, ".hist"))) bos.mkdir(os.path.join(mdir, ".hist"))
except: except:
pass pass
os.rename(fsenc(fp), fsenc(os.path.join(mdir, ".hist", mfile2))) bos.rename(fp, os.path.join(mdir, ".hist", mfile2))
p_field, _, p_data = next(self.parser.gen) p_field, _, p_data = next(self.parser.gen)
if p_field != "body": if p_field != "body":
@ -1068,7 +1069,7 @@ class HttpCli(object):
with open(fsenc(fp), "wb", 512 * 1024) as f: with open(fsenc(fp), "wb", 512 * 1024) as f:
sz, sha512, _ = hashcopy(p_data, f) sz, sha512, _ = hashcopy(p_data, f)
new_lastmod = os.stat(fsenc(fp)).st_mtime new_lastmod = bos.stat(fp).st_mtime
new_lastmod3 = int(new_lastmod * 1000) new_lastmod3 = int(new_lastmod * 1000)
sha512 = sha512[:56] sha512 = sha512[:56]
@ -1113,7 +1114,7 @@ class HttpCli(object):
for ext in ["", ".gz", ".br"]: for ext in ["", ".gz", ".br"]:
try: try:
fs_path = req_path + ext fs_path = req_path + ext
st = os.stat(fsenc(fs_path)) st = bos.stat(fs_path)
file_ts = max(file_ts, st.st_mtime) file_ts = max(file_ts, st.st_mtime)
editions[ext or "plain"] = [fs_path, st.st_size] editions[ext or "plain"] = [fs_path, st.st_size]
except: except:
@ -1365,10 +1366,10 @@ class HttpCli(object):
html_path = os.path.join(E.mod, "web", "{}.html".format(tpl)) html_path = os.path.join(E.mod, "web", "{}.html".format(tpl))
template = self.j2(tpl) template = self.j2(tpl)
st = os.stat(fsenc(fs_path)) st = bos.stat(fs_path)
ts_md = st.st_mtime ts_md = st.st_mtime
st = os.stat(fsenc(html_path)) st = bos.stat(html_path)
ts_html = st.st_mtime ts_html = st.st_mtime
sz_md = 0 sz_md = 0
@ -1585,7 +1586,7 @@ class HttpCli(object):
dbv, vrem = vn.get_dbv(rem) dbv, vrem = vn.get_dbv(rem)
try: try:
st = os.stat(fsenc(abspath)) st = bos.stat(abspath)
except: except:
raise Pebkac(404) raise Pebkac(404)
@ -1601,7 +1602,7 @@ class HttpCli(object):
if is_dir: if is_dir:
for fn in self.args.th_covers.split(","): for fn in self.args.th_covers.split(","):
fp = os.path.join(abspath, fn) fp = os.path.join(abspath, fn)
if os.path.exists(fp): if bos.path.exists(fp):
vrem = "{}/{}".format(vrem.rstrip("/"), fn) vrem = "{}/{}".format(vrem.rstrip("/"), fn)
is_dir = False is_dir = False
break break
@ -1675,7 +1676,7 @@ class HttpCli(object):
logues = ["", ""] logues = ["", ""]
for n, fn in enumerate([".prologue.html", ".epilogue.html"]): for n, fn in enumerate([".prologue.html", ".epilogue.html"]):
fn = os.path.join(abspath, fn) fn = os.path.join(abspath, fn)
if os.path.exists(fsenc(fn)): if bos.path.exists(fn):
with open(fsenc(fn), "rb") as f: with open(fsenc(fn), "rb") as f:
logues[n] = f.read().decode("utf-8") logues[n] = f.read().decode("utf-8")
@ -1739,7 +1740,7 @@ class HttpCli(object):
histdir = os.path.join(fsroot, ".hist") histdir = os.path.join(fsroot, ".hist")
ptn = re.compile(r"(.*)\.([0-9]+\.[0-9]{3})(\.[^\.]+)$") ptn = re.compile(r"(.*)\.([0-9]+\.[0-9]{3})(\.[^\.]+)$")
try: try:
for hfn in os.listdir(histdir): for hfn in bos.listdir(histdir):
m = ptn.match(hfn) m = ptn.match(hfn)
if not m: if not m:
continue continue
@ -1780,7 +1781,7 @@ class HttpCli(object):
fspath = fsroot + "/" + fn fspath = fsroot + "/" + fn
try: try:
inf = stats.get(fn) or os.stat(fsenc(fspath)) inf = stats.get(fn) or bos.stat(fspath)
except: except:
self.log("broken symlink: {}".format(repr(fspath))) self.log("broken symlink: {}".format(repr(fspath)))
continue continue

View file

@ -28,6 +28,7 @@ except ImportError:
from .__init__ import E, PY2, MACOS from .__init__ import E, PY2, MACOS
from .util import spack, min_ex, start_stackmon, start_log_thrs from .util import spack, min_ex, start_stackmon, start_log_thrs
from .bos import bos
from .httpconn import HttpConn from .httpconn import HttpConn
if PY2: if PY2:
@ -73,7 +74,7 @@ class HttpSrv(object):
} }
cert_path = os.path.join(E.cfg, "cert.pem") cert_path = os.path.join(E.cfg, "cert.pem")
if os.path.exists(cert_path): if bos.path.exists(cert_path):
self.cert_path = cert_path self.cert_path = cert_path
else: else:
self.cert_path = None self.cert_path = None

View file

@ -9,6 +9,7 @@ import subprocess as sp
from .__init__ import PY2, WINDOWS, unicode from .__init__ import PY2, WINDOWS, unicode
from .util import fsenc, fsdec, uncyg, REKOBO_LKEY from .util import fsenc, fsdec, uncyg, REKOBO_LKEY
from .bos import bos
def have_ff(cmd): def have_ff(cmd):
@ -44,7 +45,7 @@ class MParser(object):
if WINDOWS: if WINDOWS:
bp = uncyg(bp) bp = uncyg(bp)
if os.path.exists(bp): if bos.path.exists(bp):
self.bin = bp self.bin = bp
return return
except: except:
@ -420,7 +421,7 @@ class MTag(object):
except Exception as ex: except Exception as ex:
return self.get_ffprobe(abspath) if self.can_ffprobe else {} return self.get_ffprobe(abspath) if self.can_ffprobe else {}
sz = os.path.getsize(fsenc(abspath)) sz = bos.path.getsize(abspath)
ret = {".q": [0, int((sz / md.info.length) / 128)]} ret = {".q": [0, int((sz / md.info.length) / 128)]}
for attr, k, norm in [ for attr, k, norm in [

View file

@ -1,12 +1,12 @@
# coding: utf-8 # coding: utf-8
from __future__ import print_function, unicode_literals from __future__ import print_function, unicode_literals
import os
import tarfile import tarfile
import threading import threading
from .sutil import errdesc from .sutil import errdesc
from .util import Queue, fsenc from .util import Queue, fsenc
from .bos import bos
class QFile(object): class QFile(object):
@ -61,7 +61,7 @@ class StreamTar(object):
yield None yield None
if self.errf: if self.errf:
os.unlink(self.errf["ap"]) bos.unlink(self.errf["ap"])
def ser(self, f): def ser(self, f):
name = f["vp"] name = f["vp"]

View file

@ -1,11 +1,12 @@
# coding: utf-8 # coding: utf-8
from __future__ import print_function, unicode_literals from __future__ import print_function, unicode_literals
import os
import time import time
import tempfile import tempfile
from datetime import datetime from datetime import datetime
from .bos import bos
def errdesc(errors): def errdesc(errors):
report = ["copyparty failed to add the following files to the archive:", ""] report = ["copyparty failed to add the following files to the archive:", ""]
@ -20,9 +21,9 @@ def errdesc(errors):
dt = datetime.utcfromtimestamp(time.time()) dt = datetime.utcfromtimestamp(time.time())
dt = dt.strftime("%Y-%m%d-%H%M%S") dt = dt.strftime("%Y-%m%d-%H%M%S")
os.chmod(tf_path, 0o444) bos.chmod(tf_path, 0o444)
return { return {
"vp": "archive-errors-{}.txt".format(dt), "vp": "archive-errors-{}.txt".format(dt),
"ap": tf_path, "ap": tf_path,
"st": os.stat(tf_path), "st": bos.stat(tf_path),
}, report }, report

View file

@ -8,6 +8,7 @@ from datetime import datetime
from .sutil import errdesc from .sutil import errdesc
from .util import yieldfile, sanitize_fn, spack, sunpack from .util import yieldfile, sanitize_fn, spack, sunpack
from .bos import bos
def dostime2unix(buf): def dostime2unix(buf):
@ -271,4 +272,4 @@ class StreamZip(object):
yield self._ct(ecdr) yield self._ct(ecdr)
if errors: if errors:
os.unlink(errf["ap"]) bos.unlink(errf["ap"])

View file

@ -5,6 +5,7 @@ import os
from .util import Cooldown from .util import Cooldown
from .th_srv import thumb_path, THUMBABLE, FMT_FF from .th_srv import thumb_path, THUMBABLE, FMT_FF
from .bos import bos
class ThumbCli(object): class ThumbCli(object):
@ -36,7 +37,7 @@ class ThumbCli(object):
tpath = thumb_path(histpath, rem, mtime, fmt) tpath = thumb_path(histpath, rem, mtime, fmt)
ret = None ret = None
try: try:
st = os.stat(tpath) st = bos.stat(tpath)
if st.st_size: if st.st_size:
ret = tpath ret = tpath
else: else:

View file

@ -11,6 +11,7 @@ import subprocess as sp
from .__init__ import PY2, unicode from .__init__ import PY2, unicode
from .util import fsenc, vsplit, runcmd, Queue, Cooldown, BytesIO, min_ex from .util import fsenc, vsplit, runcmd, Queue, Cooldown, BytesIO, min_ex
from .bos import bos
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, ffprobe from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, ffprobe
@ -155,12 +156,12 @@ class ThumbSrv(object):
except: except:
thdir = os.path.dirname(tpath) thdir = os.path.dirname(tpath)
try: try:
os.makedirs(thdir) bos.makedirs(thdir)
except: except:
pass pass
inf_path = os.path.join(thdir, "dir.txt") inf_path = os.path.join(thdir, "dir.txt")
if not os.path.exists(inf_path): if not bos.path.exists(inf_path):
with open(inf_path, "wb") as f: with open(inf_path, "wb") as f:
f.write(fsenc(os.path.dirname(abspath))) f.write(fsenc(os.path.dirname(abspath)))
@ -180,7 +181,7 @@ class ThumbSrv(object):
cond.wait(3) cond.wait(3)
try: try:
st = os.stat(tpath) st = bos.stat(tpath)
if st.st_size: if st.st_size:
return tpath return tpath
except: except:
@ -197,7 +198,7 @@ class ThumbSrv(object):
abspath, tpath = task abspath, tpath = task
ext = abspath.split(".")[-1].lower() ext = abspath.split(".")[-1].lower()
fun = None fun = None
if not os.path.exists(tpath): if not bos.path.exists(tpath):
if ext in FMT_PIL: if ext in FMT_PIL:
fun = self.conv_pil fun = self.conv_pil
elif ext in FMT_FF: elif ext in FMT_FF:
@ -323,7 +324,7 @@ class ThumbSrv(object):
p1 = os.path.dirname(tdir) p1 = os.path.dirname(tdir)
p2 = os.path.dirname(p1) p2 = os.path.dirname(p1)
for dp in [tdir, p1, p2]: for dp in [tdir, p1, p2]:
os.utime(fsenc(dp), (ts, ts)) bos.utime(dp, (ts, ts))
except: except:
pass pass
@ -350,7 +351,7 @@ class ThumbSrv(object):
prev_b64 = None prev_b64 = None
prev_fp = None prev_fp = None
try: try:
ents = os.listdir(thumbpath) ents = bos.listdir(thumbpath)
except: except:
return 0 return 0
@ -361,7 +362,7 @@ class ThumbSrv(object):
# "top" or b64 prefix/full (a folder) # "top" or b64 prefix/full (a folder)
if len(f) <= 3 or len(f) == 24: if len(f) <= 3 or len(f) == 24:
age = now - os.path.getmtime(fp) age = now - bos.path.getmtime(fp)
if age > maxage: if age > maxage:
with self.mutex: with self.mutex:
safe = True safe = True
@ -393,7 +394,7 @@ class ThumbSrv(object):
if b64 == prev_b64: if b64 == prev_b64:
self.log("rm replaced [{}]".format(fp)) self.log("rm replaced [{}]".format(fp))
os.unlink(prev_fp) bos.unlink(prev_fp)
prev_b64 = b64 prev_b64 = b64
prev_fp = fp prev_fp = fp

View file

@ -9,6 +9,7 @@ from datetime import datetime
from .__init__ import unicode from .__init__ import unicode
from .util import s3dec, Pebkac, min_ex from .util import s3dec, Pebkac, min_ex
from .bos import bos
from .up2k import up2k_wark_from_hashlist from .up2k import up2k_wark_from_hashlist
@ -67,7 +68,7 @@ class U2idx(object):
histpath = self.asrv.vfs.histtab[ptop] histpath = self.asrv.vfs.histtab[ptop]
db_path = os.path.join(histpath, "up2k.db") db_path = os.path.join(histpath, "up2k.db")
if not os.path.exists(db_path): if not bos.path.exists(db_path):
return None return None
cur = sqlite3.connect(db_path, 2).cursor() cur = sqlite3.connect(db_path, 2).cursor()

View file

@ -34,6 +34,7 @@ from .util import (
s2hms, s2hms,
min_ex, min_ex,
) )
from .bos import bos
from .authsrv import AuthSrv from .authsrv import AuthSrv
from .mtag import MTag, MParser from .mtag import MTag, MParser
@ -214,7 +215,7 @@ class Up2k(object):
# only need to protect register_vpath but all in one go feels right # only need to protect register_vpath but all in one go feels right
for vol in vols: for vol in vols:
try: try:
os.listdir(vol.realpath) bos.listdir(vol.realpath)
except: except:
self.volstate[vol.vpath] = "OFFLINE (cannot access folder)" self.volstate[vol.vpath] = "OFFLINE (cannot access folder)"
self.log("cannot access " + vol.realpath, c=1) self.log("cannot access " + vol.realpath, c=1)
@ -352,14 +353,14 @@ class Up2k(object):
reg = {} reg = {}
path = os.path.join(histpath, "up2k.snap") path = os.path.join(histpath, "up2k.snap")
if "e2d" in flags and os.path.exists(path): if "e2d" in flags and bos.path.exists(path):
with gzip.GzipFile(path, "rb") as f: with gzip.GzipFile(path, "rb") as f:
j = f.read().decode("utf-8") j = f.read().decode("utf-8")
reg2 = json.loads(j) reg2 = json.loads(j)
for k, job in reg2.items(): for k, job in reg2.items():
path = os.path.join(job["ptop"], job["prel"], job["name"]) path = os.path.join(job["ptop"], job["prel"], job["name"])
if os.path.exists(fsenc(path)): if bos.path.exists(path):
reg[k] = job reg[k] = job
job["poke"] = time.time() job["poke"] = time.time()
else: else:
@ -375,7 +376,7 @@ class Up2k(object):
return None return None
try: try:
os.makedirs(histpath) bos.makedirs(histpath)
except: except:
pass pass
@ -519,7 +520,7 @@ class Up2k(object):
# almost zero overhead dw # almost zero overhead dw
self.pp.msg = "b{} {}".format(nfiles - nchecked, abspath) self.pp.msg = "b{} {}".format(nfiles - nchecked, abspath)
try: try:
if not os.path.exists(fsenc(abspath)): if not bos.path.exists(abspath):
rm.append([drd, dfn]) rm.append([drd, dfn])
except Exception as ex: except Exception as ex:
self.log("stat-rm: {} @ [{}]".format(repr(ex), abspath)) self.log("stat-rm: {} @ [{}]".format(repr(ex), abspath))
@ -907,7 +908,7 @@ class Up2k(object):
# x.set_trace_callback(trace) # x.set_trace_callback(trace)
def _open_db(self, db_path): def _open_db(self, db_path):
existed = os.path.exists(db_path) existed = bos.path.exists(db_path)
cur = self._orz(db_path) cur = self._orz(db_path)
ver = self._read_ver(cur) ver = self._read_ver(cur)
if not existed and ver is None: if not existed and ver is None:
@ -933,7 +934,7 @@ class Up2k(object):
db = cur.connection db = cur.connection
cur.close() cur.close()
db.close() db.close()
os.unlink(db_path) bos.unlink(db_path)
return self._create_db(db_path, None) return self._create_db(db_path, None)
def _backup_db(self, db_path, cur, ver, msg): def _backup_db(self, db_path, cur, ver, msg):
@ -1029,7 +1030,7 @@ class Up2k(object):
dp_abs = "/".join([cj["ptop"], dp_dir, dp_fn]) dp_abs = "/".join([cj["ptop"], dp_dir, dp_fn])
# relying on path.exists to return false on broken symlinks # relying on path.exists to return false on broken symlinks
if os.path.exists(fsenc(dp_abs)): if bos.path.exists(dp_abs):
job = { job = {
"name": dp_fn, "name": dp_fn,
"prel": dp_dir, "prel": dp_dir,
@ -1053,7 +1054,7 @@ class Up2k(object):
for fn in names: for fn in names:
path = os.path.join(job["ptop"], job["prel"], fn) path = os.path.join(job["ptop"], job["prel"], fn)
try: try:
if os.path.getsize(fsenc(path)) > 0: if bos.path.getsize(path) > 0:
# upload completed or both present # upload completed or both present
break break
except: except:
@ -1087,7 +1088,7 @@ class Up2k(object):
job["name"] = self._untaken(pdir, cj["name"], now, cj["addr"]) job["name"] = self._untaken(pdir, cj["name"], now, cj["addr"])
dst = os.path.join(job["ptop"], job["prel"], job["name"]) dst = os.path.join(job["ptop"], job["prel"], job["name"])
if not self.args.nw: if not self.args.nw:
os.unlink(fsenc(dst)) # TODO ed pls bos.unlink(dst) # TODO ed pls
self._symlink(src, dst) self._symlink(src, dst)
if cur: if cur:
@ -1152,8 +1153,8 @@ class Up2k(object):
try: try:
lsrc = src lsrc = src
ldst = dst ldst = dst
fs1 = os.stat(fsenc(os.path.split(src)[0])).st_dev fs1 = bos.stat(os.path.split(src)[0]).st_dev
fs2 = os.stat(fsenc(os.path.split(dst)[0])).st_dev fs2 = bos.stat(os.path.split(dst)[0]).st_dev
if fs1 == 0: if fs1 == 0:
# py2 on winxp or other unsupported combination # py2 on winxp or other unsupported combination
raise OSError() raise OSError()
@ -1283,8 +1284,8 @@ class Up2k(object):
atop = vn.canonical(rem) atop = vn.canonical(rem)
adir, fn = os.path.split(atop) adir, fn = os.path.split(atop)
fun = os.lstat if os.supports_follow_symlinks else os.stat fun = bos.lstat if os.supports_follow_symlinks else bos.stat
st = fun(fsenc(atop)) st = fun(atop)
if stat.S_ISLNK(st.st_mode) or stat.S_ISREG(st.st_mode): if stat.S_ISLNK(st.st_mode) or stat.S_ISREG(st.st_mode):
g = [[os.path.dirname(vpath), adir, [[fn, 0]], [], []]] g = [[os.path.dirname(vpath), adir, [[fn, 0]], [], []]]
else: else:
@ -1307,12 +1308,12 @@ class Up2k(object):
cur, wark = self._find_from_vpath(ptop, vrem) cur, wark = self._find_from_vpath(ptop, vrem)
self._forget_file(ptop, vpath, cur, wark) self._forget_file(ptop, vpath, cur, wark)
os.unlink(abspath) bos.unlink(abspath)
n_dirs = 0 n_dirs = 0
for d in dirs.keys(): for d in dirs.keys():
try: try:
os.rmdir(d) bos.rmdir(d)
n_dirs += 1 n_dirs += 1
except: except:
pass pass
@ -1329,7 +1330,7 @@ class Up2k(object):
if not srem: if not srem:
raise Pebkac(400, "mv: cannot move a mountpoint") raise Pebkac(400, "mv: cannot move a mountpoint")
if os.path.exists(dabs): if bos.path.exists(dabs):
raise Pebkac(400, "mv: target file exists") raise Pebkac(400, "mv: target file exists")
c1, w = self._find_from_vpath(svn.realpath, srem) c1, w = self._find_from_vpath(svn.realpath, srem)
@ -1345,15 +1346,15 @@ class Up2k(object):
slabs = "{}/{}".join(rd, fn).strip("/") slabs = "{}/{}".join(rd, fn).strip("/")
slabs = absreal(os.path.join(dvn.realpath, slabs)) slabs = absreal(os.path.join(dvn.realpath, slabs))
if os.path.exists(fsenc(slabs)): if bos.path.exists(slabs):
self.log("mv: quick relink, nice") self.log("mv: quick relink, nice")
self._symlink(fsenc(slabs), fsenc(dabs)) self._symlink(slabs, dabs)
st = os.stat(fsenc(sabs)) st = bos.stat(sabs)
self.db_add(c2, w, drd, dfn, st.st_mtime, st.st_size) self.db_add(c2, w, drd, dfn, st.st_mtime, st.st_size)
os.unlink(fsenc(sabs)) bos.unlink(sabs)
else: else:
self.log("mv: file in db missing? whatever, fixed") self.log("mv: file in db missing? whatever, fixed")
os.rename(fsenc(sabs), fsenc(slabs)) bos.rename(sabs, slabs)
self._forget_file(svn.realpath, srem, c1, w) self._forget_file(svn.realpath, srem, c1, w)
return "k" return "k"
@ -1362,9 +1363,9 @@ class Up2k(object):
self.log("mv: plain move") self.log("mv: plain move")
self._copy_tags(c1, c2, w) self._copy_tags(c1, c2, w)
self._forget_file(svn.realpath, srem, c1, w) self._forget_file(svn.realpath, srem, c1, w)
st = os.stat(fsenc(sabs)) st = bos.stat(sabs)
self.db_add(c2, w, drd, dfn, st.st_mtime, st.st_size) self.db_add(c2, w, drd, dfn, st.st_mtime, st.st_size)
os.rename(fsenc(sabs), fsenc(dabs)) bos.rename(sabs, dabs)
return "k" return "k"
def _copy_tags(self, csrc, cdst, wark): def _copy_tags(self, csrc, cdst, wark):
@ -1455,7 +1456,7 @@ class Up2k(object):
links = {} links = {}
for vp in dupes: for vp in dupes:
ap = gabs(vp) ap = gabs(vp)
d = links if os.path.islink(ap) else full d = links if bos.path.islink(ap) else full
d[vp] = ap d[vp] = ap
if not vp2 and not full: if not vp2 and not full:
@ -1464,17 +1465,17 @@ class Up2k(object):
dabs = links.pop(dvp) dabs = links.pop(dvp)
sabs = gabs(vp1) sabs = gabs(vp1)
self.log("linkswap [{}] and [{}]".format(sabs, dabs)) self.log("linkswap [{}] and [{}]".format(sabs, dabs))
os.unlink(dabs) bos.unlink(dabs)
os.rename(sabs, dabs) bos.rename(sabs, dabs)
os.link(sabs, dabs) self._symlink(sabs, dabs)
full[vp1] = sabs full[vp1] = sabs
dvp = vp2 if vp2 else full.keys()[0] dvp = vp2 if vp2 else full.keys()[0]
dabs = gabs(dvp) dabs = gabs(dvp)
for alink in links.values(): for alink in links.values():
self.log("relinking [{}] to [{}]".format(alink, dabs)) self.log("relinking [{}] to [{}]".format(alink, dabs))
os.unlink(alink) bos.unlink(alink)
os.link(alink, dabs) self._symlink(alink, dabs)
def _get_wark(self, cj): def _get_wark(self, cj):
if len(cj["name"]) > 1024 or len(cj["hash"]) > 512 * 1024: # 16TiB if len(cj["name"]) > 1024 or len(cj["hash"]) > 512 * 1024: # 16TiB
@ -1497,7 +1498,7 @@ class Up2k(object):
def _hashlist_from_file(self, path): def _hashlist_from_file(self, path):
pp = self.pp if hasattr(self, "pp") else None pp = self.pp if hasattr(self, "pp") else None
fsz = os.path.getsize(fsenc(path)) fsz = bos.path.getsize(path)
csz = up2k_chunksize(fsz) csz = up2k_chunksize(fsz)
ret = [] ret = []
with open(fsenc(path), "rb", 512 * 1024) as f: with open(fsenc(path), "rb", 512 * 1024) as f:
@ -1565,7 +1566,7 @@ class Up2k(object):
for path, sz, times in ready: for path, sz, times in ready:
self.log("lmod: setting times {} on {}".format(times, path)) self.log("lmod: setting times {} on {}".format(times, path))
try: try:
os.utime(fsenc(path), times) bos.utime(path, times)
except: except:
self.log("lmod: failed to utime ({}, {})".format(path, times)) self.log("lmod: failed to utime ({}, {})".format(path, times))
@ -1601,13 +1602,13 @@ class Up2k(object):
try: try:
# remove the filename reservation # remove the filename reservation
path = os.path.join(job["ptop"], job["prel"], job["name"]) path = os.path.join(job["ptop"], job["prel"], job["name"])
if os.path.getsize(fsenc(path)) == 0: if bos.path.getsize(path) == 0:
os.unlink(fsenc(path)) bos.unlink(path)
if len(job["hash"]) == len(job["need"]): if len(job["hash"]) == len(job["need"]):
# PARTIAL is empty, delete that too # PARTIAL is empty, delete that too
path = os.path.join(job["ptop"], job["prel"], job["tnam"]) path = os.path.join(job["ptop"], job["prel"], job["tnam"])
os.unlink(fsenc(path)) bos.unlink(path)
except: except:
pass pass
@ -1615,8 +1616,8 @@ class Up2k(object):
if not reg: if not reg:
if ptop not in self.snap_prev or self.snap_prev[ptop] is not None: if ptop not in self.snap_prev or self.snap_prev[ptop] is not None:
self.snap_prev[ptop] = None self.snap_prev[ptop] = None
if os.path.exists(fsenc(path)): if bos.path.exists(path):
os.unlink(fsenc(path)) bos.unlink(path)
return return
newest = max(x["poke"] for _, x in reg.items()) if reg else 0 newest = max(x["poke"] for _, x in reg.items()) if reg else 0
@ -1625,7 +1626,7 @@ class Up2k(object):
return return
try: try:
os.makedirs(histpath) bos.makedirs(histpath)
except: except:
pass pass
@ -1692,7 +1693,7 @@ class Up2k(object):
abspath = os.path.join(ptop, rd, fn) abspath = os.path.join(ptop, rd, fn)
self.log("hashing " + abspath) self.log("hashing " + abspath)
inf = os.stat(fsenc(abspath)) inf = bos.stat(abspath)
hashes = self._hashlist_from_file(abspath) hashes = self._hashlist_from_file(abspath)
wark = up2k_wark_from_hashlist(self.salt, inf.st_size, hashes) wark = up2k_wark_from_hashlist(self.salt, inf.st_size, hashes)
with self.mutex: with self.mutex: