mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
unlink files before replacing them
to avoid hardlink-related surprises
This commit is contained in:
parent
1088e8c6a5
commit
8b62aa7cc7
|
@ -1393,25 +1393,6 @@ class HttpCli(object):
|
|||
|
||||
path = os.path.join(fdir, fn)
|
||||
|
||||
if is_put and not self.args.no_dav:
|
||||
# allow overwrite if...
|
||||
# * volflag 'daw' is set
|
||||
# * and account has delete-access
|
||||
# or...
|
||||
# * file exists and is empty
|
||||
# * and there is no .PARTIAL
|
||||
|
||||
tnam = fn + ".PARTIAL"
|
||||
if self.args.dotpart:
|
||||
tnam = "." + tnam
|
||||
|
||||
if (vfs.flags.get("daw") and self.can_delete) or (
|
||||
not bos.path.exists(os.path.join(fdir, tnam))
|
||||
and bos.path.exists(path)
|
||||
and not bos.path.getsize(path)
|
||||
):
|
||||
params["overwrite"] = "a"
|
||||
|
||||
if xbu:
|
||||
at = time.time() - lifetime
|
||||
if not runhook(
|
||||
|
@ -1430,6 +1411,26 @@ class HttpCli(object):
|
|||
self.log(t, 1)
|
||||
raise Pebkac(403, t)
|
||||
|
||||
if is_put and not self.args.no_dav:
|
||||
# allow overwrite if...
|
||||
# * volflag 'daw' is set
|
||||
# * and account has delete-access
|
||||
# or...
|
||||
# * file exists and is empty
|
||||
# * and there is no .PARTIAL
|
||||
|
||||
tnam = fn + ".PARTIAL"
|
||||
if self.args.dotpart:
|
||||
tnam = "." + tnam
|
||||
|
||||
if (vfs.flags.get("daw") and self.can_delete) or (
|
||||
not bos.path.exists(os.path.join(fdir, tnam))
|
||||
and bos.path.exists(path)
|
||||
and not bos.path.getsize(path)
|
||||
):
|
||||
# small toctou, but better than clobbering a hardlink
|
||||
bos.unlink(path)
|
||||
|
||||
with ren_open(fn, *open_a, **params) as zfw:
|
||||
f, fn = zfw["orz"]
|
||||
path = os.path.join(fdir, fn)
|
||||
|
@ -2300,7 +2301,7 @@ class HttpCli(object):
|
|||
raise Pebkac(400, "could not read lastmod from request")
|
||||
|
||||
nullwrite = self.args.nw
|
||||
vfs, rem = self.asrv.vfs.get(self.vpath, self.uname, False, True)
|
||||
vfs, rem = self.asrv.vfs.get(self.vpath, self.uname, True, True)
|
||||
self._assert_safe_rem(rem)
|
||||
|
||||
clen = int(self.headers.get("content-length", -1))
|
||||
|
@ -2382,6 +2383,9 @@ class HttpCli(object):
|
|||
if p_field != "body":
|
||||
raise Pebkac(400, "expected body, got {}".format(p_field))
|
||||
|
||||
if bos.path.exists(fp):
|
||||
bos.unlink(fp)
|
||||
|
||||
with open(fsenc(fp), "wb", 512 * 1024) as f:
|
||||
sz, sha512, _ = hashcopy(p_data, f, self.args.s_wr_slp)
|
||||
|
||||
|
|
|
@ -1153,20 +1153,12 @@ def ren_open(
|
|||
fun = kwargs.pop("fun", open)
|
||||
fdir = kwargs.pop("fdir", None)
|
||||
suffix = kwargs.pop("suffix", None)
|
||||
overwrite = kwargs.pop("overwrite", None)
|
||||
|
||||
if fname == os.devnull:
|
||||
with fun(fname, *args, **kwargs) as f:
|
||||
yield {"orz": (f, fname)}
|
||||
return
|
||||
|
||||
if overwrite:
|
||||
assert fdir
|
||||
fpath = os.path.join(fdir, fname)
|
||||
with fun(fsenc(fpath), *args, **kwargs) as f:
|
||||
yield {"orz": (f, fname)}
|
||||
return
|
||||
|
||||
if suffix:
|
||||
ext = fname.split(".")[-1]
|
||||
if len(ext) < 7:
|
||||
|
|
Loading…
Reference in a new issue