windows: optimize sparse file creation;

previously shelled out to system32/fsutil.exe; expensive and
pointless since all it does is call DeviceIoControl (ioctl)

this is not a security fix; just like most software on windows,
copyparty is still vulnerable to DLL hijacking, so this change
makes little-to-no difference security-wise; commit bb40804f2d

plus, the default config (sharing current folder read-write
without auth) was meant to be obviously insecure, intended for
quick shares on a small LAN rather than untrusted networks
This commit is contained in:
ed 2026-07-27 17:20:25 +00:00
parent bb40804f2d
commit bc45299b86
3 changed files with 20 additions and 4 deletions

View file

@ -1334,7 +1334,7 @@ def add_upload(ap):
ap2.add_argument("--nrand", metavar="NUM", type=int, default=9, help="randomized filenames length (volflag=nrand)") ap2.add_argument("--nrand", metavar="NUM", type=int, default=9, help="randomized filenames length (volflag=nrand)")
ap2.add_argument("--magic", action="store_true", help="enable filetype detection on nameless uploads (volflag=magic)") ap2.add_argument("--magic", action="store_true", help="enable filetype detection on nameless uploads (volflag=magic)")
ap2.add_argument("--df", metavar="GiB", type=u, default="0", help="ensure \033[33mGiB\033[0m free disk space by rejecting upload requests; assumes gigabytes unless a unit suffix is given: [\033[32m256m\033[0m], [\033[32m4\033[0m], [\033[32m2T\033[0m] (volflag=df)") ap2.add_argument("--df", metavar="GiB", type=u, default="0", help="ensure \033[33mGiB\033[0m free disk space by rejecting upload requests; assumes gigabytes unless a unit suffix is given: [\033[32m256m\033[0m], [\033[32m4\033[0m], [\033[32m2T\033[0m] (volflag=df)")
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("--sparse", metavar="MiB", type=int, default=1, 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; [\033[32m-1\033[0m] = forbidden/always-off, [\033[32m0\033[0m] = default-off and warn if enabled, [\033[32m1\033[0m] = default-off, [\033[32m2\033[0m] = on, [\033[32m3\033[0m] = on and disable datecheck") ap2.add_argument("--turbo", metavar="LVL", type=int, default=0, help="configure turbo-mode in up2k client; [\033[32m-1\033[0m] = forbidden/always-off, [\033[32m0\033[0m] = default-off and warn if enabled, [\033[32m1\033[0m] = default-off, [\033[32m2\033[0m] = on, [\033[32m3\033[0m] = on and disable datecheck")
ap2.add_argument("--nosubtle", metavar="N", type=int, default=0, help="when to use a wasm-hasher instead of the browser's builtin; faster on chrome, but buggy in older chrome versions. [\033[32m0\033[0m] = only when necessary (non-https), [\033[32m1\033[0m] = always (all browsers), [\033[32m2\033[0m] = always on chrome/firefox, [\033[32m3\033[0m] = always on chrome, [\033[32mN\033[0m] = chrome-version N and newer (recommendation: 137)") ap2.add_argument("--nosubtle", metavar="N", type=int, default=0, help="when to use a wasm-hasher instead of the browser's builtin; faster on chrome, but buggy in older chrome versions. [\033[32m0\033[0m] = only when necessary (non-https), [\033[32m1\033[0m] = always (all browsers), [\033[32m2\033[0m] = always on chrome/firefox, [\033[32m3\033[0m] = always on chrome, [\033[32mN\033[0m] = chrome-version N and newer (recommendation: 137)")
ap2.add_argument("--u2j", metavar="JOBS", type=int, default=2, help="web-client: number of file chunks to upload in parallel; 1 or 2 is good when latency is low (same-country), 2~4 for android-clients, 2~6 for cross-atlantic. Max is 6 in most browsers. Big values increase network-speed but may reduce HDD-speed") ap2.add_argument("--u2j", metavar="JOBS", type=int, default=2, help="web-client: number of file chunks to upload in parallel; 1 or 2 is good when latency is low (same-country), 2~4 for android-clients, 2~6 for cross-atlantic. Max is 6 in most browsers. Big values increase network-speed but may reduce HDD-speed")

View file

@ -74,6 +74,7 @@ from .util import (
vsplit, vsplit,
w8b64dec, w8b64dec,
w8b64enc, w8b64enc,
winsparse,
wunlink, wunlink,
) )
@ -5315,9 +5316,12 @@ class Up2k(object):
and self.args.sparse * 1024 * 1024 <= sz and self.args.sparse * 1024 * 1024 <= sz
): ):
try: try:
sp.check_call(["fsutil", "sparse", "setflag", abspath]) winsparse(f)
except: # some kernels/etc are buggy; force sync:
self.log("could not sparse %r" % (abspath,), 3) f.close()
f = open(abspath, "rb+")
except Exception as ex:
self.log("could not sparse %r: %s" % (abspath, ex), 3)
relabel = True relabel = True
sprs = False sprs = False

View file

@ -4523,6 +4523,18 @@ def hidedir(dp) -> None:
pass pass
def winsparse(f: typing.BinaryIO) -> None:
assert ctypes # !rm
assert wk32 # !rm
import msvcrt
fh = msvcrt.get_osfhandle(f.fileno())
if not wk32.DeviceIoControl(
fh, 0x900C4, None, 0, None, 0, ctypes.byref(ctypes.c_ulong()), None
):
raise ctypes.WinError(ctypes.get_last_error())
_flocks = {} _flocks = {}