copyparty 1.19.9__tar.gz → 1.19.10__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.
Files changed (119) hide show
  1. {copyparty-1.19.9 → copyparty-1.19.10}/PKG-INFO +4 -4
  2. {copyparty-1.19.9 → copyparty-1.19.10}/README.md +3 -3
  3. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/__main__.py +4 -0
  4. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/__version__.py +2 -2
  5. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/broker_mpw.py +3 -0
  6. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/cfg.py +2 -0
  7. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/fsutil.py +66 -23
  8. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/mtag.py +2 -3
  9. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/svchub.py +3 -0
  10. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/up2k.py +5 -4
  11. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/util.py +7 -3
  12. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/browser.js.gz +0 -0
  13. copyparty-1.19.10/copyparty/web/up2k.js.gz +0 -0
  14. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty.egg-info/PKG-INFO +4 -4
  15. copyparty-1.19.9/copyparty/web/up2k.js.gz +0 -0
  16. {copyparty-1.19.9 → copyparty-1.19.10}/LICENSE +0 -0
  17. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/__init__.py +0 -0
  18. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/authsrv.py +0 -0
  19. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/bos/__init__.py +0 -0
  20. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/bos/bos.py +0 -0
  21. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/bos/path.py +0 -0
  22. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/broker_mp.py +0 -0
  23. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/broker_thr.py +0 -0
  24. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/broker_util.py +0 -0
  25. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/cert.py +0 -0
  26. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/dxml.py +0 -0
  27. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/ftpd.py +0 -0
  28. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/httpcli.py +0 -0
  29. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/httpconn.py +0 -0
  30. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/httpsrv.py +0 -0
  31. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/ico.py +0 -0
  32. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/mdns.py +0 -0
  33. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/metrics.py +0 -0
  34. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/multicast.py +0 -0
  35. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/pwhash.py +0 -0
  36. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/res/COPYING.txt +0 -0
  37. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/res/__init__.py +0 -0
  38. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/res/insecure.pem +0 -0
  39. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/smbd.py +0 -0
  40. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/ssdp.py +0 -0
  41. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/star.py +0 -0
  42. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/__init__.py +0 -0
  43. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/dnslib/__init__.py +0 -0
  44. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/dnslib/bimap.py +0 -0
  45. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/dnslib/bit.py +0 -0
  46. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/dnslib/buffer.py +0 -0
  47. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/dnslib/dns.py +0 -0
  48. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/dnslib/label.py +0 -0
  49. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/dnslib/lex.py +0 -0
  50. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/dnslib/ranges.py +0 -0
  51. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/ifaddr/__init__.py +0 -0
  52. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/ifaddr/_posix.py +0 -0
  53. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/ifaddr/_shared.py +0 -0
  54. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/ifaddr/_win32.py +0 -0
  55. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/qrcodegen.py +0 -0
  56. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/stolen/surrogateescape.py +0 -0
  57. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/sutil.py +0 -0
  58. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/szip.py +0 -0
  59. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/tcpsrv.py +0 -0
  60. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/tftpd.py +0 -0
  61. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/th_cli.py +0 -0
  62. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/th_srv.py +0 -0
  63. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/u2idx.py +0 -0
  64. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/a/__init__.py +0 -0
  65. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/a/partyfuse.py +0 -0
  66. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/a/u2c.py +0 -0
  67. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/a/webdav-cfg.bat +0 -0
  68. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/baguettebox.js.gz +0 -0
  69. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/browser.css.gz +0 -0
  70. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/browser.html +0 -0
  71. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/browser2.html +0 -0
  72. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/cf.html +0 -0
  73. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/dbg-audio.js.gz +0 -0
  74. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/__init__.py +0 -0
  75. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/busy.mp3.gz +0 -0
  76. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/easymde.css.gz +0 -0
  77. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/easymde.js.gz +0 -0
  78. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/fuse.py +0 -0
  79. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/marked.js.gz +0 -0
  80. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/mini-fa.css.gz +0 -0
  81. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/mini-fa.woff +0 -0
  82. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/prism.css.gz +0 -0
  83. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/prism.js.gz +0 -0
  84. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/prismd.css.gz +0 -0
  85. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/scp.woff2 +0 -0
  86. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/sha512.ac.js.gz +0 -0
  87. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/deps/sha512.hw.js.gz +0 -0
  88. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/idp.html +0 -0
  89. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/md.css.gz +0 -0
  90. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/md.html +0 -0
  91. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/md.js.gz +0 -0
  92. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/md2.css.gz +0 -0
  93. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/md2.js.gz +0 -0
  94. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/mde.css.gz +0 -0
  95. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/mde.html +0 -0
  96. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/mde.js.gz +0 -0
  97. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/msg.css.gz +0 -0
  98. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/msg.html +0 -0
  99. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/rups.css.gz +0 -0
  100. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/rups.html +0 -0
  101. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/rups.js.gz +0 -0
  102. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/shares.css.gz +0 -0
  103. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/shares.html +0 -0
  104. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/shares.js.gz +0 -0
  105. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/splash.css.gz +0 -0
  106. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/splash.html +0 -0
  107. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/splash.js.gz +0 -0
  108. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/svcs.html +0 -0
  109. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/svcs.js.gz +0 -0
  110. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/ui.css.gz +0 -0
  111. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/util.js.gz +0 -0
  112. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty/web/w.hash.js.gz +0 -0
  113. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty.egg-info/SOURCES.txt +0 -0
  114. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty.egg-info/dependency_links.txt +0 -0
  115. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty.egg-info/entry_points.txt +0 -0
  116. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty.egg-info/requires.txt +0 -0
  117. {copyparty-1.19.9 → copyparty-1.19.10}/copyparty.egg-info/top_level.txt +0 -0
  118. {copyparty-1.19.9 → copyparty-1.19.10}/pyproject.toml +0 -0
  119. {copyparty-1.19.9 → copyparty-1.19.10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copyparty
3
- Version: 1.19.9
3
+ Version: 1.19.10
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
- in order to grant full write-access to webdav clients, the volflag `daw` must be set and the account must also have delete-access (otherwise the client won't be allowed to replace the contents of existing files, which is how webdav works)
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=y` makes it much faster, but also awakens [the usual surprises](https://github.com/9001/copyparty/issues/781) you expect from a case-insensitive filesystem
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
- in order to grant full write-access to webdav clients, the volflag `daw` must be set and the account must also have delete-access (otherwise the client won't be allowed to replace the contents of existing files, which is how webdav works)
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=y` makes it much faster, but also awakens [the usual surprises](https://github.com/9001/copyparty/issues/781) you expect from a case-insensitive filesystem
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):
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- VERSION = (1, 19, 9)
3
+ VERSION = (1, 19, 10)
4
4
  CODENAME = "usernames"
5
- BUILD_DT = (2025, 9, 15)
5
+ BUILD_DT = (2025, 9, 19)
6
6
 
7
7
  S_VERSION = ".".join(map(str, VERSION))
8
8
  S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
@@ -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 build_tab(self) :
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
- tab1 = []
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
- tab1.append((str(zs1), str(zs2)))
96
- atab.append(ln)
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 = "\n".join(sorted(atab))
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
- self.log("failed to build tab:\n{}".format(min_ex()), 3)
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)
@@ -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
- cover_id = package_root.find("./metadata/meta[@name='cover']", package_ns).get(
430
- "content"
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
- no_stdout = self.args.q
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(0.1)
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 > 10:
1056
+ if msg and now - tp >= slp_pr:
1053
1057
  tp = now
1054
1058
  self.log("progress: %r" % (msg,), 6)
1055
1059
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: copyparty
3
- Version: 1.19.9
3
+ Version: 1.19.10
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
- in order to grant full write-access to webdav clients, the volflag `daw` must be set and the account must also have delete-access (otherwise the client won't be allowed to replace the contents of existing files, which is how webdav works)
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=y` makes it much faster, but also awakens [the usual surprises](https://github.com/9001/copyparty/issues/781) you expect from a case-insensitive filesystem
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