copyparty 1.19.9__tar.gz → 1.19.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {copyparty-1.19.9 → copyparty-1.19.11}/PKG-INFO +4 -4
- {copyparty-1.19.9 → copyparty-1.19.11}/README.md +3 -3
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/__main__.py +4 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/__version__.py +2 -2
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/broker_mpw.py +3 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/cfg.py +2 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/fsutil.py +66 -23
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/ftpd.py +7 -6
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/mtag.py +2 -3
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/svchub.py +3 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/up2k.py +5 -4
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/util.py +7 -3
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/browser.js.gz +0 -0
- copyparty-1.19.11/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty.egg-info/PKG-INFO +4 -4
- copyparty-1.19.9/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/LICENSE +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/__init__.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/authsrv.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/bos/bos.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/bos/path.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/broker_mp.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/broker_thr.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/broker_util.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/cert.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/dxml.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/httpcli.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/httpconn.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/httpsrv.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/ico.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/mdns.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/metrics.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/multicast.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/pwhash.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/res/__init__.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/smbd.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/ssdp.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/star.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/dnslib/dns.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/ifaddr/__init__.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/ifaddr/_shared.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/qrcodegen.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/sutil.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/szip.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/tcpsrv.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/tftpd.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/th_cli.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/th_srv.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/u2idx.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/a/u2c.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/baguettebox.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/browser.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/browser.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/browser2.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/cf.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/busy.mp3.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/easymde.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/fuse.py +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/marked.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/idp.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/md.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/md.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/mde.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/msg.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/rups.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/rups.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/rups.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/shares.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/shares.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/shares.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/splash.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/svcs.html +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/ui.css.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/util.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/pyproject.toml +0 -0
- {copyparty-1.19.9 → copyparty-1.19.11}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: copyparty
|
|
3
|
-
Version: 1.19.
|
|
3
|
+
Version: 1.19.11
|
|
4
4
|
Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
|
|
5
5
|
Author-email: ed <copyparty@ocv.me>
|
|
6
6
|
License: MIT
|
|
@@ -1418,7 +1418,7 @@ general usage:
|
|
|
1418
1418
|
on macos, connect from finder:
|
|
1419
1419
|
* [Go] -> [Connect to Server...] -> http://192.168.123.1:3923/
|
|
1420
1420
|
|
|
1421
|
-
|
|
1421
|
+
to upload or edit files with WebDAV clients, enable the `daw` volflag (because most WebDAV clients expect this) and give your account the delete-permission. This avoids getting several copies of the same file on the server. HOWEVER: This will also make all PUT-uploads overwrite existing files if the user has delete-access, so use with caution.
|
|
1422
1422
|
|
|
1423
1423
|
> note: if you have enabled [IdP authentication](#identity-providers) then that may cause issues for some/most webdav clients; see [the webdav section in the IdP docs](https://github.com/9001/copyparty/blob/hovudstraum/docs/idp.md#connecting-webdav-clients)
|
|
1424
1424
|
|
|
@@ -2771,7 +2771,7 @@ below are some tweaks roughly ordered by usefulness:
|
|
|
2771
2771
|
* and pypy can sometimes crash on startup with `-j0` (TODO make issue)
|
|
2772
2772
|
|
|
2773
2773
|
* if you are running the copyparty server **on Windows or Macos:**
|
|
2774
|
-
* `--casechk=
|
|
2774
|
+
* `--casechk=n` makes it much faster, but also awakens [the usual surprises](https://github.com/9001/copyparty/issues/781) you expect from a case-insensitive filesystem
|
|
2775
2775
|
* this is the same as `casechk: n` in a config-file
|
|
2776
2776
|
|
|
2777
2777
|
|
|
@@ -3088,7 +3088,7 @@ first install one of the following:
|
|
|
3088
3088
|
and then copypaste the following command into `a-Shell`:
|
|
3089
3089
|
|
|
3090
3090
|
```sh
|
|
3091
|
-
curl https://github.com/9001/copyparty/raw/refs/heads/hovudstraum/contrib/setup-ashell.sh | sh
|
|
3091
|
+
curl -L https://github.com/9001/copyparty/raw/refs/heads/hovudstraum/contrib/setup-ashell.sh | sh
|
|
3092
3092
|
```
|
|
3093
3093
|
|
|
3094
3094
|
what this does:
|
|
@@ -1353,7 +1353,7 @@ general usage:
|
|
|
1353
1353
|
on macos, connect from finder:
|
|
1354
1354
|
* [Go] -> [Connect to Server...] -> http://192.168.123.1:3923/
|
|
1355
1355
|
|
|
1356
|
-
|
|
1356
|
+
to upload or edit files with WebDAV clients, enable the `daw` volflag (because most WebDAV clients expect this) and give your account the delete-permission. This avoids getting several copies of the same file on the server. HOWEVER: This will also make all PUT-uploads overwrite existing files if the user has delete-access, so use with caution.
|
|
1357
1357
|
|
|
1358
1358
|
> note: if you have enabled [IdP authentication](#identity-providers) then that may cause issues for some/most webdav clients; see [the webdav section in the IdP docs](https://github.com/9001/copyparty/blob/hovudstraum/docs/idp.md#connecting-webdav-clients)
|
|
1359
1359
|
|
|
@@ -2706,7 +2706,7 @@ below are some tweaks roughly ordered by usefulness:
|
|
|
2706
2706
|
* and pypy can sometimes crash on startup with `-j0` (TODO make issue)
|
|
2707
2707
|
|
|
2708
2708
|
* if you are running the copyparty server **on Windows or Macos:**
|
|
2709
|
-
* `--casechk=
|
|
2709
|
+
* `--casechk=n` makes it much faster, but also awakens [the usual surprises](https://github.com/9001/copyparty/issues/781) you expect from a case-insensitive filesystem
|
|
2710
2710
|
* this is the same as `casechk: n` in a config-file
|
|
2711
2711
|
|
|
2712
2712
|
|
|
@@ -3023,7 +3023,7 @@ first install one of the following:
|
|
|
3023
3023
|
and then copypaste the following command into `a-Shell`:
|
|
3024
3024
|
|
|
3025
3025
|
```sh
|
|
3026
|
-
curl https://github.com/9001/copyparty/raw/refs/heads/hovudstraum/contrib/setup-ashell.sh | sh
|
|
3026
|
+
curl -L https://github.com/9001/copyparty/raw/refs/heads/hovudstraum/contrib/setup-ashell.sh | sh
|
|
3027
3027
|
```
|
|
3028
3028
|
|
|
3029
3029
|
what this does:
|
|
@@ -1212,6 +1212,7 @@ def add_upload(ap):
|
|
|
1212
1212
|
ap2.add_argument("--chmod-d", metavar="UGO", type=u, default="755", help="unix file permissions to use when creating directories; see --help-chmod. Examples: [\033[32m755\033[0m] = owner-RW + all-R, [\033[32m777\033[0m] = full-yolo (volflag=chmod_d)")
|
|
1213
1213
|
ap2.add_argument("--uid", metavar="N", type=int, default=-1, help="unix user-id to chown new files/folders to; default = -1 = do-not-change (volflag=uid)")
|
|
1214
1214
|
ap2.add_argument("--gid", metavar="N", type=int, default=-1, help="unix group-id to chown new files/folders to; default = -1 = do-not-change (volflag=gid)")
|
|
1215
|
+
ap2.add_argument("--wram", action="store_true", help="allow uploading even if a volume is inside a ramdisk, meaning that all data will be lost on the next server reboot (volflag=wram)")
|
|
1215
1216
|
ap2.add_argument("--dedup", action="store_true", help="enable symlink-based upload deduplication (volflag=dedup)")
|
|
1216
1217
|
ap2.add_argument("--safe-dedup", metavar="N", type=int, default=50, help="how careful to be when deduplicating files; [\033[32m1\033[0m] = just verify the filesize, [\033[32m50\033[0m] = verify file contents have not been altered (volflag=safededup)")
|
|
1217
1218
|
ap2.add_argument("--hardlink", action="store_true", help="enable hardlink-based dedup; will fallback on symlinks when that is impossible (across filesystems) (volflag=hardlink)")
|
|
@@ -1569,6 +1570,9 @@ def add_logging(ap):
|
|
|
1569
1570
|
ap2.add_argument("--ihead", metavar="HEADER", type=u, action='append', help="print request \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
|
1570
1571
|
ap2.add_argument("--ohead", metavar="HEADER", type=u, action='append', help="print response \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
|
1571
1572
|
ap2.add_argument("--lf-url", metavar="RE", type=u, default=r"^/\.cpr/|[?&]th=[wjp]|/\.(_|ql_|DS_Store$|localized$)", help="dont log URLs matching regex \033[33mRE\033[0m")
|
|
1573
|
+
ap2.add_argument("--scan-st-r", metavar="SEC", type=float, default=0.1, help="fs-indexing: wait \033[33mSEC\033[0m between each status-message")
|
|
1574
|
+
ap2.add_argument("--scan-pr-r", metavar="SEC", type=float, default=10, help="fs-indexing: wait \033[33mSEC\033[0m between each 'progress:' message")
|
|
1575
|
+
ap2.add_argument("--scan-pr-s", metavar="MiB", type=float, default=1, help="fs-indexing: say 'file: <name>' when a file larger than \033[33mMiB\033[0m is about to be hashed")
|
|
1572
1576
|
|
|
1573
1577
|
|
|
1574
1578
|
def add_admin(ap):
|
|
@@ -12,6 +12,7 @@ import queue
|
|
|
12
12
|
from .__init__ import ANYWIN
|
|
13
13
|
from .authsrv import AuthSrv
|
|
14
14
|
from .broker_util import BrokerCli, ExceptionalQueue, NotExQueue
|
|
15
|
+
from .fsutil import ramdisk_chk
|
|
15
16
|
from .httpsrv import HttpSrv
|
|
16
17
|
from .util import FAKE_MP, Daemon, HMaccas
|
|
17
18
|
|
|
@@ -50,6 +51,7 @@ class MpWorker(BrokerCli):
|
|
|
50
51
|
|
|
51
52
|
# starting to look like a good idea
|
|
52
53
|
self.asrv = AuthSrv(args, None, False)
|
|
54
|
+
ramdisk_chk(self.asrv)
|
|
53
55
|
|
|
54
56
|
# instantiate all services here (TODO: inheritance?)
|
|
55
57
|
self.iphash = HMaccas(os.path.join(self.args.E.cfg, "iphash"), 8)
|
|
@@ -93,6 +95,7 @@ class MpWorker(BrokerCli):
|
|
|
93
95
|
if dest == "reload":
|
|
94
96
|
self.logw("mpw.asrv reloading")
|
|
95
97
|
self.asrv.reload()
|
|
98
|
+
ramdisk_chk(self.asrv)
|
|
96
99
|
self.logw("mpw.asrv reloaded")
|
|
97
100
|
continue
|
|
98
101
|
|
|
@@ -57,6 +57,7 @@ def vf_bmap() :
|
|
|
57
57
|
"rmagic",
|
|
58
58
|
"rss",
|
|
59
59
|
"wo_up_readme",
|
|
60
|
+
"wram",
|
|
60
61
|
"xdev",
|
|
61
62
|
"xlink",
|
|
62
63
|
"xvol",
|
|
@@ -187,6 +188,7 @@ flagcats = {
|
|
|
187
188
|
"chmod_f=644": "unix-permission for new files",
|
|
188
189
|
"uid=573": "change owner of new files/folders to unix-user 573",
|
|
189
190
|
"gid=999": "change owner of new files/folders to unix-group 999",
|
|
191
|
+
"wram": "allow uploading into ramdisks",
|
|
190
192
|
"sparse": "force use of sparse files, mainly for s3-backed storage",
|
|
191
193
|
"nosparse": "deny use of sparse files, mainly for slow storage",
|
|
192
194
|
"daw": "enable full WebDAV write support (dangerous);\nPUT-operations will now \033[1;31mOVERWRITE\033[0;35m existing files",
|
|
@@ -7,27 +7,30 @@ import re
|
|
|
7
7
|
import time
|
|
8
8
|
|
|
9
9
|
from .__init__ import ANYWIN, MACOS
|
|
10
|
-
from .authsrv import AXS, VFS
|
|
10
|
+
from .authsrv import AXS, VFS, AuthSrv
|
|
11
11
|
from .bos import bos
|
|
12
12
|
from .util import chkcmd, min_ex, undot
|
|
13
13
|
|
|
14
14
|
class Fstab(object):
|
|
15
|
-
def __init__(self, log , args ):
|
|
15
|
+
def __init__(self, log , args , verbose ):
|
|
16
16
|
self.log_func = log
|
|
17
|
+
self.verbose = verbose
|
|
17
18
|
|
|
18
19
|
self.warned = False
|
|
19
20
|
self.trusted = False
|
|
20
21
|
self.tab = None
|
|
21
22
|
self.oldtab = None
|
|
22
23
|
self.srctab = "a"
|
|
23
|
-
self.cache
|
|
24
|
+
self.cache = {}
|
|
24
25
|
self.age = 0.0
|
|
25
26
|
self.maxage = args.mtab_age
|
|
26
27
|
|
|
27
28
|
def log(self, msg , c = 0) :
|
|
29
|
+
if not c or self.verbose:
|
|
30
|
+
return
|
|
28
31
|
self.log_func("fstab", msg, c)
|
|
29
32
|
|
|
30
|
-
def get(self, path )
|
|
33
|
+
def get(self, path ) :
|
|
31
34
|
now = time.time()
|
|
32
35
|
if now - self.age > self.maxage or len(self.cache) > 9000:
|
|
33
36
|
self.age = now
|
|
@@ -35,6 +38,7 @@ class Fstab(object):
|
|
|
35
38
|
self.tab = None
|
|
36
39
|
self.cache = {}
|
|
37
40
|
|
|
41
|
+
mp = ""
|
|
38
42
|
fs = "ext4"
|
|
39
43
|
msg = "failed to determine filesystem at %r; assuming %s\n%s"
|
|
40
44
|
|
|
@@ -44,7 +48,7 @@ class Fstab(object):
|
|
|
44
48
|
path = self._winpath(path)
|
|
45
49
|
except:
|
|
46
50
|
self.log(msg % (path, fs, min_ex()), 3)
|
|
47
|
-
return fs
|
|
51
|
+
return fs, ""
|
|
48
52
|
|
|
49
53
|
path = undot(path)
|
|
50
54
|
try:
|
|
@@ -53,14 +57,14 @@ class Fstab(object):
|
|
|
53
57
|
pass
|
|
54
58
|
|
|
55
59
|
try:
|
|
56
|
-
fs = self.get_w32(path) if ANYWIN else self.get_unix(path)
|
|
60
|
+
fs, mp = self.get_w32(path) if ANYWIN else self.get_unix(path)
|
|
57
61
|
except:
|
|
58
62
|
self.log(msg % (path, fs, min_ex()), 3)
|
|
59
63
|
|
|
60
64
|
fs = fs.lower()
|
|
61
|
-
self.cache[path] = fs
|
|
62
|
-
self.log("found %s at %r" % (fs, path))
|
|
63
|
-
return fs
|
|
65
|
+
self.cache[path] = (fs, mp)
|
|
66
|
+
self.log("found %s at %r, %r" % (fs, mp, path))
|
|
67
|
+
return fs, mp
|
|
64
68
|
|
|
65
69
|
def _winpath(self, path ) :
|
|
66
70
|
# try to combine volume-label + st_dev (vsn)
|
|
@@ -75,34 +79,49 @@ class Fstab(object):
|
|
|
75
79
|
self.tab = VFS(self.log_func, "idk", "/", "/", AXS(), {})
|
|
76
80
|
self.trusted = False
|
|
77
81
|
|
|
78
|
-
def
|
|
79
|
-
self.log("inspecting mtab for changes")
|
|
80
|
-
|
|
82
|
+
def _from_sp_mount(self) :
|
|
81
83
|
sptn = r"^.*? on (.*) type ([^ ]+) \(.*"
|
|
82
84
|
if MACOS:
|
|
83
85
|
sptn = r"^.*? on (.*) \(([^ ]+), .*"
|
|
84
86
|
|
|
85
87
|
ptn = re.compile(sptn)
|
|
86
88
|
so, _ = chkcmd(["mount"])
|
|
87
|
-
|
|
88
|
-
atab = []
|
|
89
|
+
dtab = {}
|
|
89
90
|
for ln in so.split("\n"):
|
|
90
91
|
m = ptn.match(ln)
|
|
91
92
|
if not m:
|
|
92
93
|
continue
|
|
93
94
|
|
|
94
95
|
zs1, zs2 = m.groups()
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
dtab[str(zs1)] = str(zs2)
|
|
97
|
+
|
|
98
|
+
return dtab
|
|
99
|
+
|
|
100
|
+
def _from_proc(self) :
|
|
101
|
+
ret = {}
|
|
102
|
+
with open("/proc/self/mounts", "rb", 262144) as f:
|
|
103
|
+
src = f.read(262144).decode("utf-8", "replace").split("\n")
|
|
104
|
+
for zsl in [x.split(" ") for x in src]:
|
|
105
|
+
if len(zsl) < 3:
|
|
106
|
+
continue
|
|
107
|
+
zs = zsl[1]
|
|
108
|
+
zs = zs.replace("\\011", "\t").replace("\\040", " ").replace("\\134", "\\")
|
|
109
|
+
ret[zs] = zsl[2]
|
|
110
|
+
return ret
|
|
111
|
+
|
|
112
|
+
def build_tab(self) :
|
|
113
|
+
self.log("inspecting mtab for changes")
|
|
114
|
+
dtab = self._from_sp_mount() if MACOS else self._from_proc()
|
|
97
115
|
|
|
98
116
|
# keep empirically-correct values if mounttab unchanged
|
|
99
|
-
srctab =
|
|
117
|
+
srctab = str(sorted(dtab.items()))
|
|
100
118
|
if srctab == self.srctab:
|
|
101
119
|
self.tab = self.oldtab
|
|
102
120
|
return
|
|
103
121
|
|
|
104
122
|
self.log("mtab has changed; reevaluating support for sparse files")
|
|
105
123
|
|
|
124
|
+
tab1 = list(dtab.items())
|
|
106
125
|
tab1.sort(key=lambda x: (len(x[0]), x[0]))
|
|
107
126
|
path1, fs1 = tab1[0]
|
|
108
127
|
tab = VFS(self.log_func, fs1, path1, path1, AXS(), {})
|
|
@@ -139,7 +158,7 @@ class Fstab(object):
|
|
|
139
158
|
vn.realpath = ptn.sub(nval, vn.realpath)
|
|
140
159
|
visit.extend(list(vn.nodes.values()))
|
|
141
160
|
|
|
142
|
-
def get_unix(self, path )
|
|
161
|
+
def get_unix(self, path ) :
|
|
143
162
|
if not self.tab:
|
|
144
163
|
try:
|
|
145
164
|
self.build_tab()
|
|
@@ -148,18 +167,42 @@ class Fstab(object):
|
|
|
148
167
|
# prisonparty or other restrictive environment
|
|
149
168
|
if not self.warned:
|
|
150
169
|
self.warned = True
|
|
151
|
-
|
|
170
|
+
t = "failed to associate fs-mounts with the VFS (this is fine):\n%s"
|
|
171
|
+
self.log(t % (min_ex(),), 6)
|
|
152
172
|
self.build_fallback()
|
|
153
173
|
|
|
154
174
|
ret = self.tab._find(path)[0]
|
|
155
175
|
if self.trusted or path == ret.vpath:
|
|
156
|
-
return ret.realpath.split("/")[0]
|
|
176
|
+
return ret.realpath.split("/")[0], ret.vpath
|
|
157
177
|
else:
|
|
158
|
-
return "idk"
|
|
178
|
+
return "idk", ""
|
|
159
179
|
|
|
160
|
-
def get_w32(self, path )
|
|
180
|
+
def get_w32(self, path ) :
|
|
161
181
|
if not self.tab:
|
|
162
182
|
self.build_fallback()
|
|
163
183
|
|
|
164
184
|
ret = self.tab._find(path)[0]
|
|
165
|
-
return ret.realpath
|
|
185
|
+
return ret.realpath, ""
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def ramdisk_chk(asrv ) :
|
|
189
|
+
# should have been in authsrv but that's a circular import
|
|
190
|
+
mods = []
|
|
191
|
+
ramfs = ("tmpfs", "overlay")
|
|
192
|
+
log = asrv.log_func or print
|
|
193
|
+
fstab = Fstab(log, asrv.args, False)
|
|
194
|
+
for vn in asrv.vfs.all_nodes.values():
|
|
195
|
+
if not vn.axs.uwrite or "wram" in vn.flags:
|
|
196
|
+
continue
|
|
197
|
+
ap = vn.realpath
|
|
198
|
+
if not ap or os.path.isfile(ap):
|
|
199
|
+
continue
|
|
200
|
+
fs, mp = fstab.get(ap)
|
|
201
|
+
mp = "/" + mp.strip("/")
|
|
202
|
+
if fs == "tmpfs" or (mp == "/" and fs in ramfs):
|
|
203
|
+
mods.append((vn.vpath, ap, fs, mp))
|
|
204
|
+
vn.axs.uwrite.clear()
|
|
205
|
+
if mods:
|
|
206
|
+
t = "WARNING: write-access was removed from the following volumes because they are not mapped to an actual HDD for storage! All uploaded data would live in RAM only, and all uploaded files would be LOST on next reboot. To allow uploading and ignore this hazard, enable the 'wram' option (global/volflag). List of affected volumes:"
|
|
207
|
+
t2 = ["\n volume=[/%s], abspath=%r, type=%s, root=%r" % x for x in mods]
|
|
208
|
+
log("vfs", t + "".join(t2) + "\n", 1)
|
|
@@ -275,6 +275,10 @@ class FtpFs(AbstractedFS):
|
|
|
275
275
|
def chdir(self, path ) :
|
|
276
276
|
nwd = join(self.cwd, path)
|
|
277
277
|
vfs, rem = self.hub.asrv.vfs.get(nwd, self.uname, False, False)
|
|
278
|
+
if not vfs.realpath:
|
|
279
|
+
self.cwd = nwd
|
|
280
|
+
return
|
|
281
|
+
|
|
278
282
|
ap = vfs.canonical(rem)
|
|
279
283
|
try:
|
|
280
284
|
st = bos.stat(ap)
|
|
@@ -284,12 +288,9 @@ class FtpFs(AbstractedFS):
|
|
|
284
288
|
# returning 550 is library-default and suitable
|
|
285
289
|
raise FSE("No such file or directory")
|
|
286
290
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
raise FSE("Permission denied", 1)
|
|
291
|
-
else:
|
|
292
|
-
avfs = vfs
|
|
291
|
+
avfs = vfs.chk_ap(ap, st)
|
|
292
|
+
if not avfs:
|
|
293
|
+
raise FSE("Permission denied", 1)
|
|
293
294
|
|
|
294
295
|
self.cwd = nwd
|
|
295
296
|
|
|
@@ -426,9 +426,8 @@ def _get_cover_from_epub2(
|
|
|
426
426
|
) :
|
|
427
427
|
# <meta name="cover" content="id-to-cover-image"> in <metadata>, then
|
|
428
428
|
# <item> in <manifest>
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
)
|
|
429
|
+
xn = package_root.find("./metadata/meta[@name='cover']", package_ns)
|
|
430
|
+
cover_id = xn.get("content") if xn is not None else None
|
|
432
431
|
|
|
433
432
|
if not cover_id:
|
|
434
433
|
return None
|
|
@@ -24,6 +24,7 @@ from .__init__ import ANYWIN, EXE, MACOS, PY2, TYPE_CHECKING, E, EnvParams, unic
|
|
|
24
24
|
from .authsrv import BAD_CFG, AuthSrv, n_du_who, n_ver_who
|
|
25
25
|
from .bos import bos
|
|
26
26
|
from .cert import ensure_cert
|
|
27
|
+
from .fsutil import ramdisk_chk
|
|
27
28
|
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, HAVE_MUTAGEN
|
|
28
29
|
from .pwhash import HAVE_ARGON2
|
|
29
30
|
from .tcpsrv import TcpSrv
|
|
@@ -304,6 +305,7 @@ class SvcHub(object):
|
|
|
304
305
|
|
|
305
306
|
# initiate all services to manage
|
|
306
307
|
self.asrv = AuthSrv(self.args, self.log, dargs=self.dargs)
|
|
308
|
+
ramdisk_chk(self.asrv)
|
|
307
309
|
|
|
308
310
|
if args.cgen:
|
|
309
311
|
self.asrv.cgen()
|
|
@@ -1349,6 +1351,7 @@ class SvcHub(object):
|
|
|
1349
1351
|
with self.reload_mutex:
|
|
1350
1352
|
self.log("root", "reloading config")
|
|
1351
1353
|
self.asrv.reload(9 if up2k else 4)
|
|
1354
|
+
ramdisk_chk(self.asrv)
|
|
1352
1355
|
if up2k:
|
|
1353
1356
|
self.up2k.reload(rescan_all_vols)
|
|
1354
1357
|
t += "; volumes are now reinitializing"
|
|
@@ -209,7 +209,7 @@ class Up2k(object):
|
|
|
209
209
|
t = "could not initialize sqlite3, will use in-memory registry only"
|
|
210
210
|
self.log(t, 3)
|
|
211
211
|
|
|
212
|
-
self.fstab = Fstab(self.log_func, self.args)
|
|
212
|
+
self.fstab = Fstab(self.log_func, self.args, True)
|
|
213
213
|
self.gen_fk = self._gen_fk if self.args.log_fk else gen_filekey
|
|
214
214
|
|
|
215
215
|
if self.args.hash_mt < 2:
|
|
@@ -1491,6 +1491,7 @@ class Up2k(object):
|
|
|
1491
1491
|
|
|
1492
1492
|
th_cvd = self.args.th_coversd
|
|
1493
1493
|
th_cvds = self.args.th_coversd_set
|
|
1494
|
+
scan_pr_s = self.args.scan_pr_s
|
|
1494
1495
|
|
|
1495
1496
|
self.pp.msg = "a%d %s" % (self.pp.n, cdir)
|
|
1496
1497
|
|
|
@@ -1702,7 +1703,7 @@ class Up2k(object):
|
|
|
1702
1703
|
if nohash or not sz:
|
|
1703
1704
|
wark = up2k_wark_from_metadata(self.salt, sz, lmod, rd, fn)
|
|
1704
1705
|
else:
|
|
1705
|
-
if sz > 1024 * 1024:
|
|
1706
|
+
if sz > 1024 * 1024 * scan_pr_s:
|
|
1706
1707
|
self.log("file: %r" % (abspath,))
|
|
1707
1708
|
|
|
1708
1709
|
try:
|
|
@@ -2991,7 +2992,7 @@ class Up2k(object):
|
|
|
2991
2992
|
|
|
2992
2993
|
# check if filesystem supports sparse files;
|
|
2993
2994
|
# refuse out-of-order / multithreaded uploading if sprs False
|
|
2994
|
-
sprs = self.fstab.get(pdir) != "ng"
|
|
2995
|
+
sprs = self.fstab.get(pdir)[0] != "ng"
|
|
2995
2996
|
|
|
2996
2997
|
if True:
|
|
2997
2998
|
jcur = self.cur.get(ptop)
|
|
@@ -5155,7 +5156,7 @@ class Up2k(object):
|
|
|
5155
5156
|
sprs = False
|
|
5156
5157
|
|
|
5157
5158
|
if not ANYWIN and sprs and sz > 1024 * 1024:
|
|
5158
|
-
fs = self.fstab.get(pdir)
|
|
5159
|
+
fs, mnt = self.fstab.get(pdir)
|
|
5159
5160
|
if fs == "ok":
|
|
5160
5161
|
pass
|
|
5161
5162
|
elif "nosparse" in vf:
|
|
@@ -525,6 +525,8 @@ def py_desc() :
|
|
|
525
525
|
ofs = py_ver.find(".final.")
|
|
526
526
|
if ofs > 0:
|
|
527
527
|
py_ver = py_ver[:ofs]
|
|
528
|
+
if "free-threading" in sys.version:
|
|
529
|
+
py_ver += "t"
|
|
528
530
|
|
|
529
531
|
host_os = platform.system()
|
|
530
532
|
compiler = platform.python_compiler().split("http")[0]
|
|
@@ -1040,16 +1042,18 @@ class ProgressPrinter(threading.Thread):
|
|
|
1040
1042
|
sigblock()
|
|
1041
1043
|
tp = 0
|
|
1042
1044
|
msg = None
|
|
1043
|
-
|
|
1045
|
+
slp_pr = self.args.scan_pr_r
|
|
1046
|
+
slp_ps = min(slp_pr, self.args.scan_st_r)
|
|
1047
|
+
no_stdout = self.args.q or slp_pr == slp_ps
|
|
1044
1048
|
fmt = " {}\033[K\r" if VT100 else " {} $\r"
|
|
1045
1049
|
while not self.end:
|
|
1046
|
-
time.sleep(
|
|
1050
|
+
time.sleep(slp_ps)
|
|
1047
1051
|
if msg == self.msg or self.end:
|
|
1048
1052
|
continue
|
|
1049
1053
|
|
|
1050
1054
|
msg = self.msg
|
|
1051
1055
|
now = time.time()
|
|
1052
|
-
if msg and now - tp
|
|
1056
|
+
if msg and now - tp >= slp_pr:
|
|
1053
1057
|
tp = now
|
|
1054
1058
|
self.log("progress: %r" % (msg,), 6)
|
|
1055
1059
|
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: copyparty
|
|
3
|
-
Version: 1.19.
|
|
3
|
+
Version: 1.19.11
|
|
4
4
|
Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
|
|
5
5
|
Author-email: ed <copyparty@ocv.me>
|
|
6
6
|
License: MIT
|
|
@@ -1418,7 +1418,7 @@ general usage:
|
|
|
1418
1418
|
on macos, connect from finder:
|
|
1419
1419
|
* [Go] -> [Connect to Server...] -> http://192.168.123.1:3923/
|
|
1420
1420
|
|
|
1421
|
-
|
|
1421
|
+
to upload or edit files with WebDAV clients, enable the `daw` volflag (because most WebDAV clients expect this) and give your account the delete-permission. This avoids getting several copies of the same file on the server. HOWEVER: This will also make all PUT-uploads overwrite existing files if the user has delete-access, so use with caution.
|
|
1422
1422
|
|
|
1423
1423
|
> note: if you have enabled [IdP authentication](#identity-providers) then that may cause issues for some/most webdav clients; see [the webdav section in the IdP docs](https://github.com/9001/copyparty/blob/hovudstraum/docs/idp.md#connecting-webdav-clients)
|
|
1424
1424
|
|
|
@@ -2771,7 +2771,7 @@ below are some tweaks roughly ordered by usefulness:
|
|
|
2771
2771
|
* and pypy can sometimes crash on startup with `-j0` (TODO make issue)
|
|
2772
2772
|
|
|
2773
2773
|
* if you are running the copyparty server **on Windows or Macos:**
|
|
2774
|
-
* `--casechk=
|
|
2774
|
+
* `--casechk=n` makes it much faster, but also awakens [the usual surprises](https://github.com/9001/copyparty/issues/781) you expect from a case-insensitive filesystem
|
|
2775
2775
|
* this is the same as `casechk: n` in a config-file
|
|
2776
2776
|
|
|
2777
2777
|
|
|
@@ -3088,7 +3088,7 @@ first install one of the following:
|
|
|
3088
3088
|
and then copypaste the following command into `a-Shell`:
|
|
3089
3089
|
|
|
3090
3090
|
```sh
|
|
3091
|
-
curl https://github.com/9001/copyparty/raw/refs/heads/hovudstraum/contrib/setup-ashell.sh | sh
|
|
3091
|
+
curl -L https://github.com/9001/copyparty/raw/refs/heads/hovudstraum/contrib/setup-ashell.sh | sh
|
|
3092
3092
|
```
|
|
3093
3093
|
|
|
3094
3094
|
what this does:
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|