copyparty 1.18.5__tar.gz → 1.18.7__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.18.5 → copyparty-1.18.7}/PKG-INFO +32 -5
- {copyparty-1.18.5 → copyparty-1.18.7}/README.md +31 -4
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/__main__.py +32 -27
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/__version__.py +2 -2
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/authsrv.py +48 -2
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/bos/bos.py +14 -3
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/cfg.py +6 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/ftpd.py +4 -4
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/httpcli.py +75 -53
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/httpsrv.py +1 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/mtag.py +3 -2
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/smbd.py +1 -1
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/svchub.py +4 -3
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/tftpd.py +6 -3
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/th_srv.py +2 -2
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/up2k.py +14 -8
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/util.py +62 -22
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/browser.html +2 -2
- copyparty-1.18.7/copyparty/web/browser.js.gz +0 -0
- copyparty-1.18.7/copyparty/web/shares.js.gz +0 -0
- copyparty-1.18.7/copyparty/web/splash.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/svcs.html +16 -4
- copyparty-1.18.7/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty.egg-info/PKG-INFO +32 -5
- copyparty-1.18.5/copyparty/web/browser.js.gz +0 -0
- copyparty-1.18.5/copyparty/web/shares.js.gz +0 -0
- copyparty-1.18.5/copyparty/web/splash.js.gz +0 -0
- copyparty-1.18.5/copyparty/web/svcs.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/LICENSE +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/bos/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/bos/path.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/broker_mp.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/broker_mpw.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/broker_thr.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/broker_util.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/cert.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/dxml.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/fsutil.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/httpconn.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/ico.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/mdns.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/metrics.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/multicast.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/pwhash.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/res/COPYING.txt +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/res/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/res/insecure.pem +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/ssdp.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/star.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/dnslib/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/dnslib/bimap.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/dnslib/bit.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/dnslib/buffer.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/dnslib/dns.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/dnslib/label.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/dnslib/lex.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/dnslib/ranges.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/ifaddr/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/ifaddr/_posix.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/ifaddr/_shared.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/ifaddr/_win32.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/qrcodegen.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/stolen/surrogateescape.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/sutil.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/szip.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/tcpsrv.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/th_cli.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/u2idx.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/a/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/a/partyfuse.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/a/u2c.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/a/webdav-cfg.bat +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/baguettebox.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/browser.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/browser2.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/cf.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/dbg-audio.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/dd/2.png +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/dd/3.png +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/dd/4.png +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/dd/5.png +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/dd/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/__init__.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/busy.mp3.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/easymde.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/easymde.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/fuse.py +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/marked.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/mini-fa.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/mini-fa.woff +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/prism.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/prism.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/prismd.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/scp.woff2 +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/sha512.ac.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/deps/sha512.hw.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/idp.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/md.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/md.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/md.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/md2.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/md2.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/mde.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/mde.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/mde.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/msg.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/msg.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/rups.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/rups.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/rups.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/shares.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/shares.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/splash.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/splash.html +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/ui.css.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/up2k.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/util.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty/web/w.hash.js.gz +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty.egg-info/SOURCES.txt +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty.egg-info/dependency_links.txt +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty.egg-info/entry_points.txt +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty.egg-info/requires.txt +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/copyparty.egg-info/top_level.txt +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/pyproject.toml +0 -0
- {copyparty-1.18.5 → copyparty-1.18.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: copyparty
|
3
|
-
Version: 1.18.
|
3
|
+
Version: 1.18.7
|
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
|
@@ -70,7 +70,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
70
70
|
|
71
71
|
📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
|
72
72
|
|
73
|
-
🎬 **videos:** [upload](https://a.ocv.me/pub/demo/pics-vids/up2k.webm) // [cli-upload](https://a.ocv.me/pub/demo/pics-vids/u2cli.webm) // [race-the-beam](https://a.ocv.me/pub/g/nerd-stuff/cpp/2024-0418-race-the-beam.webm)
|
73
|
+
🎬 **videos:** [upload](https://a.ocv.me/pub/demo/pics-vids/up2k.webm) // [cli-upload](https://a.ocv.me/pub/demo/pics-vids/u2cli.webm) // [race-the-beam](https://a.ocv.me/pub/g/nerd-stuff/cpp/2024-0418-race-the-beam.webm) // 👉 **[feature-showcase](https://a.ocv.me/pub/demo/showcase-hq.webm)** ([youtube](https://www.youtube.com/watch?v=15_-hgsX2V0))
|
74
74
|
|
75
75
|
made in Norway 🇳🇴
|
76
76
|
|
@@ -138,6 +138,7 @@ made in Norway 🇳🇴
|
|
138
138
|
* [periodic rescan](#periodic-rescan) - filesystem monitoring
|
139
139
|
* [upload rules](#upload-rules) - set upload rules using volflags
|
140
140
|
* [compress uploads](#compress-uploads) - files can be autocompressed on upload
|
141
|
+
* [chmod and chown](#chmod-and-chown) - per-volume filesystem-permissions and ownership
|
141
142
|
* [other flags](#other-flags)
|
142
143
|
* [database location](#database-location) - in-volume (`.hist/up2k.db`, default) or somewhere else
|
143
144
|
* [metadata from audio files](#metadata-from-audio-files) - set `-e2t` to index tags on upload
|
@@ -1497,12 +1498,17 @@ if you enable deduplication with `--dedup` then it'll create a symlink instead o
|
|
1497
1498
|
**warning:** when enabling dedup, you should also:
|
1498
1499
|
* enable indexing with `-e2dsa` or volflag `e2dsa` (see [file indexing](#file-indexing) section below); strongly recommended
|
1499
1500
|
* ...and/or `--hardlink-only` to use hardlink-based deduplication instead of symlinks; see explanation below
|
1501
|
+
* ...and/or `--reflink` to use CoW/reflink-based dedup (much safer than hardlink, but OS/FS-dependent)
|
1500
1502
|
|
1501
1503
|
it will not be safe to rename/delete files if you only enable dedup and none of the above; if you enable indexing then it is not *necessary* to also do hardlinks (but you may still want to)
|
1502
1504
|
|
1503
1505
|
by default, deduplication is done based on symlinks (symbolic links); these are tiny files which are pointers to the nearest full copy of the file
|
1504
1506
|
|
1505
|
-
you can choose to use hardlinks instead of softlinks, globally with `--hardlink-only` or volflag `hardlinkonly
|
1507
|
+
you can choose to use hardlinks instead of softlinks, globally with `--hardlink-only` or volflag `hardlinkonly`, and you can choose to use reflinks with `--reflink` or volflag `reflink`
|
1508
|
+
|
1509
|
+
advantages of using reflinks (CoW, copy-on-write):
|
1510
|
+
* entirely safe (when your filesystem supports it correctly); either file can be edited or deleted without affecting other copies
|
1511
|
+
* only linux 5.3 or newer, only python 3.14 or newer, only some filesystems (btrfs probably ok, maybe xfs too, but zfs had bugs)
|
1506
1512
|
|
1507
1513
|
advantages of using hardlinks:
|
1508
1514
|
* hardlinks are more compatible with other software; they behave entirely like regular files
|
@@ -1702,6 +1708,26 @@ some examples,
|
|
1702
1708
|
allows (but does not force) gz compression if client uploads to `/inc?pk` or `/inc?gz` or `/inc?gz=4`
|
1703
1709
|
|
1704
1710
|
|
1711
|
+
## chmod and chown
|
1712
|
+
|
1713
|
+
per-volume filesystem-permissions and ownership
|
1714
|
+
|
1715
|
+
by default:
|
1716
|
+
* all folders are chmod 755
|
1717
|
+
* files are usually chmod 644 (umask-defined)
|
1718
|
+
* user/group is whatever copyparty is running as
|
1719
|
+
|
1720
|
+
this can be configured per-volume:
|
1721
|
+
* volflag `chmod_f` sets file permissions; default=`644` (usually)
|
1722
|
+
* volflag `chmod_d` sets directory permissions; default=`755`
|
1723
|
+
* volflag `uid` sets the owner user-id
|
1724
|
+
* volflag `gid` sets the owner group-id
|
1725
|
+
|
1726
|
+
notes:
|
1727
|
+
* `gid` can only be set to one of the groups which the copyparty process is a member of
|
1728
|
+
* `uid` can only be set if copyparty is running as root (i appreciate your faith)
|
1729
|
+
|
1730
|
+
|
1705
1731
|
## other flags
|
1706
1732
|
|
1707
1733
|
* `:c,magic` enables filetype detection for nameless uploads, same as `--magic`
|
@@ -2080,7 +2106,7 @@ some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatical
|
|
2080
2106
|
* **warning:** nginx-QUIC (HTTP/3) is still experimental and can make uploads much slower, so HTTP/1.1 is recommended for now
|
2081
2107
|
* depending on server/client, HTTP/1.1 can also be 5x faster than HTTP/2
|
2082
2108
|
|
2083
|
-
for improved security (and a 10% performance boost) consider listening on a unix-socket with `-i unix:770:www:/
|
2109
|
+
for improved security (and a 10% performance boost) consider listening on a unix-socket with `-i unix:770:www:/dev/shm/party.sock` (permission `770` means only members of group `www` can access it)
|
2084
2110
|
|
2085
2111
|
example webserver / reverse-proxy configs:
|
2086
2112
|
|
@@ -2279,6 +2305,7 @@ force-enable features with known issues on your OS/env by setting any of the fo
|
|
2279
2305
|
| env-var | what it does |
|
2280
2306
|
| ------------------------ | ------------ |
|
2281
2307
|
| `PRTY_FORCE_MP` | force-enable multiprocessing (real multithreading) on MacOS and other broken platforms |
|
2308
|
+
| `PRTY_FORCE_MAGIC` | use [magic](https://pypi.org/project/python-magic/) on Windows (you will segfault) |
|
2282
2309
|
|
2283
2310
|
|
2284
2311
|
# packages
|
@@ -2301,7 +2328,7 @@ NOTE: there used to be an aur package; this evaporated when copyparty was adopte
|
|
2301
2328
|
|
2302
2329
|
## fedora package
|
2303
2330
|
|
2304
|
-
does not exist yet;
|
2331
|
+
does not exist yet; there are rumours that it is being packaged! keep an eye on this space...
|
2305
2332
|
|
2306
2333
|
|
2307
2334
|
## nix package
|
@@ -12,7 +12,7 @@ turn almost any device into a file server with resumable uploads/downloads using
|
|
12
12
|
|
13
13
|
📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [unpost](#unpost) // [thumbnails](#thumbnails) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [md-viewer](#markdown-viewer)
|
14
14
|
|
15
|
-
🎬 **videos:** [upload](https://a.ocv.me/pub/demo/pics-vids/up2k.webm) // [cli-upload](https://a.ocv.me/pub/demo/pics-vids/u2cli.webm) // [race-the-beam](https://a.ocv.me/pub/g/nerd-stuff/cpp/2024-0418-race-the-beam.webm)
|
15
|
+
🎬 **videos:** [upload](https://a.ocv.me/pub/demo/pics-vids/up2k.webm) // [cli-upload](https://a.ocv.me/pub/demo/pics-vids/u2cli.webm) // [race-the-beam](https://a.ocv.me/pub/g/nerd-stuff/cpp/2024-0418-race-the-beam.webm) // 👉 **[feature-showcase](https://a.ocv.me/pub/demo/showcase-hq.webm)** ([youtube](https://www.youtube.com/watch?v=15_-hgsX2V0))
|
16
16
|
|
17
17
|
made in Norway 🇳🇴
|
18
18
|
|
@@ -80,6 +80,7 @@ made in Norway 🇳🇴
|
|
80
80
|
* [periodic rescan](#periodic-rescan) - filesystem monitoring
|
81
81
|
* [upload rules](#upload-rules) - set upload rules using volflags
|
82
82
|
* [compress uploads](#compress-uploads) - files can be autocompressed on upload
|
83
|
+
* [chmod and chown](#chmod-and-chown) - per-volume filesystem-permissions and ownership
|
83
84
|
* [other flags](#other-flags)
|
84
85
|
* [database location](#database-location) - in-volume (`.hist/up2k.db`, default) or somewhere else
|
85
86
|
* [metadata from audio files](#metadata-from-audio-files) - set `-e2t` to index tags on upload
|
@@ -1439,12 +1440,17 @@ if you enable deduplication with `--dedup` then it'll create a symlink instead o
|
|
1439
1440
|
**warning:** when enabling dedup, you should also:
|
1440
1441
|
* enable indexing with `-e2dsa` or volflag `e2dsa` (see [file indexing](#file-indexing) section below); strongly recommended
|
1441
1442
|
* ...and/or `--hardlink-only` to use hardlink-based deduplication instead of symlinks; see explanation below
|
1443
|
+
* ...and/or `--reflink` to use CoW/reflink-based dedup (much safer than hardlink, but OS/FS-dependent)
|
1442
1444
|
|
1443
1445
|
it will not be safe to rename/delete files if you only enable dedup and none of the above; if you enable indexing then it is not *necessary* to also do hardlinks (but you may still want to)
|
1444
1446
|
|
1445
1447
|
by default, deduplication is done based on symlinks (symbolic links); these are tiny files which are pointers to the nearest full copy of the file
|
1446
1448
|
|
1447
|
-
you can choose to use hardlinks instead of softlinks, globally with `--hardlink-only` or volflag `hardlinkonly
|
1449
|
+
you can choose to use hardlinks instead of softlinks, globally with `--hardlink-only` or volflag `hardlinkonly`, and you can choose to use reflinks with `--reflink` or volflag `reflink`
|
1450
|
+
|
1451
|
+
advantages of using reflinks (CoW, copy-on-write):
|
1452
|
+
* entirely safe (when your filesystem supports it correctly); either file can be edited or deleted without affecting other copies
|
1453
|
+
* only linux 5.3 or newer, only python 3.14 or newer, only some filesystems (btrfs probably ok, maybe xfs too, but zfs had bugs)
|
1448
1454
|
|
1449
1455
|
advantages of using hardlinks:
|
1450
1456
|
* hardlinks are more compatible with other software; they behave entirely like regular files
|
@@ -1644,6 +1650,26 @@ some examples,
|
|
1644
1650
|
allows (but does not force) gz compression if client uploads to `/inc?pk` or `/inc?gz` or `/inc?gz=4`
|
1645
1651
|
|
1646
1652
|
|
1653
|
+
## chmod and chown
|
1654
|
+
|
1655
|
+
per-volume filesystem-permissions and ownership
|
1656
|
+
|
1657
|
+
by default:
|
1658
|
+
* all folders are chmod 755
|
1659
|
+
* files are usually chmod 644 (umask-defined)
|
1660
|
+
* user/group is whatever copyparty is running as
|
1661
|
+
|
1662
|
+
this can be configured per-volume:
|
1663
|
+
* volflag `chmod_f` sets file permissions; default=`644` (usually)
|
1664
|
+
* volflag `chmod_d` sets directory permissions; default=`755`
|
1665
|
+
* volflag `uid` sets the owner user-id
|
1666
|
+
* volflag `gid` sets the owner group-id
|
1667
|
+
|
1668
|
+
notes:
|
1669
|
+
* `gid` can only be set to one of the groups which the copyparty process is a member of
|
1670
|
+
* `uid` can only be set if copyparty is running as root (i appreciate your faith)
|
1671
|
+
|
1672
|
+
|
1647
1673
|
## other flags
|
1648
1674
|
|
1649
1675
|
* `:c,magic` enables filetype detection for nameless uploads, same as `--magic`
|
@@ -2022,7 +2048,7 @@ some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatical
|
|
2022
2048
|
* **warning:** nginx-QUIC (HTTP/3) is still experimental and can make uploads much slower, so HTTP/1.1 is recommended for now
|
2023
2049
|
* depending on server/client, HTTP/1.1 can also be 5x faster than HTTP/2
|
2024
2050
|
|
2025
|
-
for improved security (and a 10% performance boost) consider listening on a unix-socket with `-i unix:770:www:/
|
2051
|
+
for improved security (and a 10% performance boost) consider listening on a unix-socket with `-i unix:770:www:/dev/shm/party.sock` (permission `770` means only members of group `www` can access it)
|
2026
2052
|
|
2027
2053
|
example webserver / reverse-proxy configs:
|
2028
2054
|
|
@@ -2221,6 +2247,7 @@ force-enable features with known issues on your OS/env by setting any of the fo
|
|
2221
2247
|
| env-var | what it does |
|
2222
2248
|
| ------------------------ | ------------ |
|
2223
2249
|
| `PRTY_FORCE_MP` | force-enable multiprocessing (real multithreading) on MacOS and other broken platforms |
|
2250
|
+
| `PRTY_FORCE_MAGIC` | use [magic](https://pypi.org/project/python-magic/) on Windows (you will segfault) |
|
2224
2251
|
|
2225
2252
|
|
2226
2253
|
# packages
|
@@ -2243,7 +2270,7 @@ NOTE: there used to be an aur package; this evaporated when copyparty was adopte
|
|
2243
2270
|
|
2244
2271
|
## fedora package
|
2245
2272
|
|
2246
|
-
does not exist yet;
|
2273
|
+
does not exist yet; there are rumours that it is being packaged! keep an eye on this space...
|
2247
2274
|
|
2248
2275
|
|
2249
2276
|
## nix package
|
@@ -53,13 +53,13 @@ from .util import (
|
|
53
53
|
PYFTPD_VER,
|
54
54
|
RAM_AVAIL,
|
55
55
|
RAM_TOTAL,
|
56
|
+
RE_ANSI,
|
56
57
|
SQLITE_VER,
|
57
58
|
UNPLICATIONS,
|
58
59
|
URL_BUG,
|
59
60
|
URL_PRJ,
|
60
61
|
Daemon,
|
61
62
|
align_tab,
|
62
|
-
ansi_re,
|
63
63
|
b64enc,
|
64
64
|
dedent,
|
65
65
|
has_resource,
|
@@ -161,7 +161,7 @@ def lprint(*a , **ka ) :
|
|
161
161
|
txt = " ".join(unicode(x) for x in a) + eol
|
162
162
|
printed.append(txt)
|
163
163
|
if not VT100:
|
164
|
-
txt =
|
164
|
+
txt = RE_ANSI.sub("", txt)
|
165
165
|
|
166
166
|
print(txt, end="", **ka)
|
167
167
|
|
@@ -539,14 +539,15 @@ def get_sects():
|
|
539
539
|
when running behind a reverse-proxy, it's recommended to
|
540
540
|
use unix-sockets for improved performance and security;
|
541
541
|
|
542
|
-
\033[32m-i unix:770:www:\033[33m/
|
543
|
-
|
544
|
-
|
542
|
+
\033[32m-i unix:770:www:\033[33m/dev/shm/party.sock\033[0m listens on
|
543
|
+
\033[33m/dev/shm/party.sock\033[0m with permissions \033[33m0770\033[0m;
|
544
|
+
only accessible to members of the \033[33mwww\033[0m group.
|
545
|
+
This is the best approach. Alternatively,
|
545
546
|
|
546
|
-
\033[32m-i unix:777:\033[33m/
|
547
|
-
access it; bad unless it's inside a restricted folder
|
547
|
+
\033[32m-i unix:777:\033[33m/dev/shm/party.sock\033[0m sets perms \033[33m0777\033[0m so anyone
|
548
|
+
can access it; bad unless it's inside a restricted folder
|
548
549
|
|
549
|
-
\033[32m-i unix:\033[33m/
|
550
|
+
\033[32m-i unix:\033[33m/dev/shm/party.sock\033[0m keeps umask-defined permission
|
550
551
|
(usually \033[33m0600\033[0m) and the same user/group as copyparty
|
551
552
|
|
552
553
|
\033[33m-p\033[0m (tcp ports) is ignored for unix sockets
|
@@ -864,31 +865,31 @@ def get_sects():
|
|
864
865
|
|
865
866
|
similarly, \033[33m--chmod-d\033[0m and \033[33mchmod_d\033[0m sets the directory/folder perm
|
866
867
|
|
867
|
-
the value is a three-digit octal number such as
|
868
|
+
the value is a three-digit octal number such as \033[32m755\033[0m, \033[32m750\033[0m, \033[32m644\033[0m, etc.
|
868
869
|
|
869
870
|
first digit = "User"; permission for the unix-user
|
870
871
|
second digit = "Group"; permission for the unix-group
|
871
872
|
third digit = "Other"; permission for all other users/groups
|
872
873
|
|
873
874
|
for files:
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
875
|
+
\033[32m0\033[0m = \033[35m---\033[0m = no access
|
876
|
+
\033[32m1\033[0m = \033[35m--x\033[0m = can execute the file as a program
|
877
|
+
\033[32m2\033[0m = \033[35m-w-\033[0m = can write
|
878
|
+
\033[32m3\033[0m = \033[35m-wx\033[0m = can write and execute
|
879
|
+
\033[32m4\033[0m = \033[35mr--\033[0m = can read
|
880
|
+
\033[32m5\033[0m = \033[35mr-x\033[0m = can read and execute
|
881
|
+
\033[32m6\033[0m = \033[35mrw-\033[0m = can read and write
|
882
|
+
\033[32m7\033[0m = \033[35mrwx\033[0m = can read, write, execute
|
882
883
|
|
883
884
|
for directories/folders:
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
885
|
+
\033[32m0\033[0m = \033[35m---\033[0m = no access
|
886
|
+
\033[32m1\033[0m = \033[35m--x\033[0m = can read files in folder but not list contents
|
887
|
+
\033[32m2\033[0m = \033[35m-w-\033[0m = n/a
|
888
|
+
\033[32m3\033[0m = \033[35m-wx\033[0m = can create files but not list
|
889
|
+
\033[32m4\033[0m = \033[35mr--\033[0m = can list, but not read/write
|
890
|
+
\033[32m5\033[0m = \033[35mr-x\033[0m = can list and read files
|
891
|
+
\033[32m6\033[0m = \033[35mrw-\033[0m = n/a
|
892
|
+
\033[32m7\033[0m = \033[35mrwx\033[0m = can read, write, list
|
892
893
|
"""
|
893
894
|
),
|
894
895
|
],
|
@@ -1044,10 +1045,13 @@ def add_upload(ap):
|
|
1044
1045
|
ap2.add_argument("--use-fpool", action="store_true", help="force file-handle pooling, even when it might be dangerous (multiprocessing, filesystems lacking sparse-files support, ...)")
|
1045
1046
|
ap2.add_argument("--chmod-f", metavar="UGO", type=u, default="", help="unix file permissions to use when creating files; default is probably 644 (OS-decided), see --help-chmod. Examples: [\033[32m644\033[0m] = owner-RW + all-R, [\033[32m755\033[0m] = owner-RWX + all-RX, [\033[32m777\033[0m] = full-yolo (volflag=chmod_f)")
|
1046
1047
|
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)")
|
1048
|
+
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)")
|
1049
|
+
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)")
|
1047
1050
|
ap2.add_argument("--dedup", action="store_true", help="enable symlink-based upload deduplication (volflag=dedup)")
|
1048
1051
|
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)")
|
1049
1052
|
ap2.add_argument("--hardlink", action="store_true", help="enable hardlink-based dedup; will fallback on symlinks when that is impossible (across filesystems) (volflag=hardlink)")
|
1050
1053
|
ap2.add_argument("--hardlink-only", action="store_true", help="do not fallback to symlinks when a hardlink cannot be made (volflag=hardlinkonly)")
|
1054
|
+
ap2.add_argument("--reflink", action="store_true", help="enable reflink-based dedup; will fallback on full copies when that is impossible (non-CoW filesystem) (volflag=reflink)")
|
1051
1055
|
ap2.add_argument("--no-dupe", action="store_true", help="reject duplicate files during upload; only matches within the same volume (volflag=nodupe)")
|
1052
1056
|
ap2.add_argument("--no-clone", action="store_true", help="do not use existing data on disk to satisfy dupe uploads; reduces server HDD reads in exchange for much more network load (volflag=noclone)")
|
1053
1057
|
ap2.add_argument("--no-snap", action="store_true", help="disable snapshots -- forget unfinished uploads on shutdown; don't create .hist/up2k.snap files -- abandoned/interrupted uploads must be cleaned up manually")
|
@@ -1328,6 +1332,7 @@ def add_safety(ap):
|
|
1328
1332
|
ap2.add_argument("--no-robots", action="store_true", help="adds http and html headers asking search engines to not index anything (volflag=norobots)")
|
1329
1333
|
ap2.add_argument("--logout", metavar="H", type=float, default=8086.0, help="logout clients after \033[33mH\033[0m hours of inactivity; [\033[32m0.0028\033[0m]=10sec, [\033[32m0.1\033[0m]=6min, [\033[32m24\033[0m]=day, [\033[32m168\033[0m]=week, [\033[32m720\033[0m]=month, [\033[32m8760\033[0m]=year)")
|
1330
1334
|
ap2.add_argument("--ban-pw", metavar="N,W,B", type=u, default="9,60,1440", help="more than \033[33mN\033[0m wrong passwords in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; disable with [\033[32mno\033[0m]")
|
1335
|
+
ap2.add_argument("--ban-pwc", metavar="N,W,B", type=u, default="5,60,1440", help="more than \033[33mN\033[0m password-changes in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; disable with [\033[32mno\033[0m]")
|
1331
1336
|
ap2.add_argument("--ban-404", metavar="N,W,B", type=u, default="50,60,1440", help="hitting more than \033[33mN\033[0m 404's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; only affects users who cannot see directory listings because their access is either g/G/h")
|
1332
1337
|
ap2.add_argument("--ban-403", metavar="N,W,B", type=u, default="9,2,1440", help="hitting more than \033[33mN\033[0m 403's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes; [\033[32m1440\033[0m]=day, [\033[32m10080\033[0m]=week, [\033[32m43200\033[0m]=month")
|
1333
1338
|
ap2.add_argument("--ban-422", metavar="N,W,B", type=u, default="9,2,1440", help="hitting more than \033[33mN\033[0m 422's in \033[33mW\033[0m minutes = ban for \033[33mB\033[0m minutes (invalid requests, attempted exploits ++)")
|
@@ -1544,7 +1549,7 @@ def add_ui(ap, retry):
|
|
1544
1549
|
ap2.add_argument("--hsortn", metavar="N", type=int, default=2, help="number of sorting rules to include in media URLs by default (volflag=hsortn)")
|
1545
1550
|
ap2.add_argument("--see-dots", action="store_true", help="default-enable seeing dotfiles; only takes effect if user has the necessary permissions")
|
1546
1551
|
ap2.add_argument("--qdel", metavar="LVL", type=int, default=2, help="number of confirmations to show when deleting files (2/1/0)")
|
1547
|
-
ap2.add_argument("--unlist", metavar="REGEX", type=u, default="", help="don't show files matching \033[33mREGEX\033[0m in file list. Purely cosmetic! Does not affect API calls, just the browser. Example: [\033[32m\\.(js|css)$\033[0m] (volflag=unlist)")
|
1552
|
+
ap2.add_argument("--unlist", metavar="REGEX", type=u, default="", help="don't show files/folders matching \033[33mREGEX\033[0m in file list. WARNING: Purely cosmetic! Does not affect API calls, just the browser. Example: [\033[32m\\.(js|css)$\033[0m] (volflag=unlist)")
|
1548
1553
|
ap2.add_argument("--favico", metavar="TXT", type=u, default="c 000 none" if retry else "🎉 000 none", help="\033[33mfavicon-text\033[0m [ \033[33mforeground\033[0m [ \033[33mbackground\033[0m ] ], set blank to disable")
|
1549
1554
|
ap2.add_argument("--ext-th", metavar="E=VP", type=u, action="append", help="use thumbnail-image \033[33mVP\033[0m for file-extension \033[33mE\033[0m, example: [\033[32mexe=/.res/exe.png\033[0m] (volflag=ext_th)")
|
1550
1555
|
ap2.add_argument("--mpmc", metavar="URL", type=u, default="", help="change the mediaplayer-toggle mouse cursor; URL to a folder with {2..5}.png inside (or disable with [\033[32m.\033[0m])")
|
@@ -1558,7 +1563,7 @@ def add_ui(ap, retry):
|
|
1558
1563
|
ap2.add_argument("--txt-max", metavar="KiB", type=int, default=64, help="max size of embedded textfiles on ?doc= (anything bigger will be lazy-loaded by JS)")
|
1559
1564
|
ap2.add_argument("--doctitle", metavar="TXT", type=u, default="copyparty @ --name", help="title / service-name to show in html documents")
|
1560
1565
|
ap2.add_argument("--bname", metavar="TXT", type=u, default="--name", help="server name (displayed in filebrowser document title)")
|
1561
|
-
ap2.add_argument("--pb-url", metavar="URL", type=u, default=URL_PRJ, help="powered-by link; disable with \033[33m-
|
1566
|
+
ap2.add_argument("--pb-url", metavar="URL", type=u, default=URL_PRJ, help="powered-by link; disable with \033[33m-nb\033[0m")
|
1562
1567
|
ap2.add_argument("--ver", action="store_true", help="show version on the control panel (incompatible with \033[33m-nb\033[0m)")
|
1563
1568
|
ap2.add_argument("--k304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable k304 on the controlpanel (workaround for buggy reverse-proxies); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on")
|
1564
1569
|
ap2.add_argument("--no304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable no304 on the controlpanel (workaround for buggy caching in browsers); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on")
|
@@ -33,6 +33,7 @@ from .util import (
|
|
33
33
|
afsenc,
|
34
34
|
get_df,
|
35
35
|
humansize,
|
36
|
+
json_hesc,
|
36
37
|
min_ex,
|
37
38
|
odfusion,
|
38
39
|
read_utf8,
|
@@ -63,6 +64,25 @@ if PY2:
|
|
63
64
|
|
64
65
|
|
65
66
|
LEELOO_DALLAS = "leeloo_dallas"
|
67
|
+
##
|
68
|
+
## you might be curious what Leeloo Dallas is doing here, so let me explain:
|
69
|
+
##
|
70
|
+
## certain daemonic tasks, namely:
|
71
|
+
## * deletion of expired files, running on a timer
|
72
|
+
## * deletion of sidecar files, initiated by plugins
|
73
|
+
## need to skip the usual permission-checks to do their thing,
|
74
|
+
## so we let Leeloo handle these
|
75
|
+
##
|
76
|
+
## and also, the smb-server has really shitty support for user-accounts
|
77
|
+
## so one popular way to avoid issues is by running copyparty without users;
|
78
|
+
## this makes all smb-clients identify as LD to gain unrestricted access
|
79
|
+
##
|
80
|
+
## Leeloo, being a fictional character from The Fifth Element,
|
81
|
+
## obviously does not exist and will never be able to access any copyparty
|
82
|
+
## instances from the outside (the username is rejected at every entrypoint)
|
83
|
+
##
|
84
|
+
## thanks for coming to my ted talk
|
85
|
+
|
66
86
|
|
67
87
|
SEE_LOG = "see log for details"
|
68
88
|
SEESLOG = " (see serverlog for details)"
|
@@ -114,6 +134,8 @@ class Lim(object):
|
|
114
134
|
self.reg = None # up2k registry
|
115
135
|
|
116
136
|
self.chmod_d = 0o755
|
137
|
+
self.uid = self.gid = -1
|
138
|
+
self.chown = False
|
117
139
|
|
118
140
|
self.nups = {} # num tracker
|
119
141
|
self.bups = {} # byte tracker list
|
@@ -276,6 +298,8 @@ class Lim(object):
|
|
276
298
|
# no branches yet; make one
|
277
299
|
sub = os.path.join(path, "0")
|
278
300
|
bos.mkdir(sub, self.chmod_d)
|
301
|
+
if self.chown:
|
302
|
+
os.chown(sub, self.uid, self.gid)
|
279
303
|
else:
|
280
304
|
# try newest branch only
|
281
305
|
sub = os.path.join(path, str(dirs[-1]))
|
@@ -291,6 +315,8 @@ class Lim(object):
|
|
291
315
|
# make a branch
|
292
316
|
sub = os.path.join(path, str(dirs[-1] + 1))
|
293
317
|
bos.mkdir(sub, self.chmod_d)
|
318
|
+
if self.chown:
|
319
|
+
os.chown(sub, self.uid, self.gid)
|
294
320
|
ret = self.dive(sub, lvs - 1)
|
295
321
|
if ret is None:
|
296
322
|
raise Pebkac(500, "rotation bug")
|
@@ -2115,6 +2141,7 @@ class AuthSrv(object):
|
|
2115
2141
|
all_mte = {}
|
2116
2142
|
errors = False
|
2117
2143
|
free_umask = False
|
2144
|
+
have_reflink = False
|
2118
2145
|
for vol in vfs.all_nodes.values():
|
2119
2146
|
if (self.args.e2ds and vol.axs.uwrite) or self.args.e2dsa:
|
2120
2147
|
vol.flags["e2ds"] = True
|
@@ -2152,7 +2179,7 @@ class AuthSrv(object):
|
|
2152
2179
|
if vf not in vol.flags:
|
2153
2180
|
vol.flags[vf] = getattr(self.args, ga)
|
2154
2181
|
|
2155
|
-
zs = "forget_ip nrand tail_who u2abort u2ow ups_who zip_who"
|
2182
|
+
zs = "forget_ip gid nrand tail_who u2abort u2ow uid ups_who zip_who"
|
2156
2183
|
for k in zs.split():
|
2157
2184
|
if k in vol.flags:
|
2158
2185
|
vol.flags[k] = int(vol.flags[k])
|
@@ -2189,8 +2216,17 @@ class AuthSrv(object):
|
|
2189
2216
|
if (is_d and zi != 0o755) or not is_d:
|
2190
2217
|
free_umask = True
|
2191
2218
|
|
2219
|
+
vol.flags.pop("chown", None)
|
2220
|
+
if vol.flags["uid"] != -1 or vol.flags["gid"] != -1:
|
2221
|
+
vol.flags["chown"] = True
|
2222
|
+
vol.flags.pop("fperms", None)
|
2223
|
+
if "chown" in vol.flags or vol.flags.get("chmod_f"):
|
2224
|
+
vol.flags["fperms"] = True
|
2192
2225
|
if vol.lim:
|
2193
2226
|
vol.lim.chmod_d = vol.flags["chmod_d"]
|
2227
|
+
vol.lim.chown = "chown" in vol.flags
|
2228
|
+
vol.lim.uid = vol.flags["uid"]
|
2229
|
+
vol.lim.gid = vol.flags["gid"]
|
2194
2230
|
|
2195
2231
|
if vol.flags.get("og"):
|
2196
2232
|
self.args.uqe = True
|
@@ -2198,6 +2234,9 @@ class AuthSrv(object):
|
|
2198
2234
|
if "unlistcr" in vol.flags or "unlistcw" in vol.flags:
|
2199
2235
|
self.args.have_unlistc = True
|
2200
2236
|
|
2237
|
+
if "reflink" in vol.flags:
|
2238
|
+
have_reflink = True
|
2239
|
+
|
2201
2240
|
zs = str(vol.flags.get("tcolor", "")).lstrip("#")
|
2202
2241
|
if len(zs) == 3: # fc5 => ffcc55
|
2203
2242
|
vol.flags["tcolor"] = "".join([x * 2 for x in zs])
|
@@ -2562,6 +2601,13 @@ class AuthSrv(object):
|
|
2562
2601
|
t = "WARNING! The following IdP volumes are mounted below another volume where other users can read and/or write files. This is a SECURITY HAZARD!! When copyparty is restarted, it will not know about these IdP volumes yet. These volumes will then be accessible by an unexpected set of permissions UNTIL one of the users associated with their volume sends a request to the server. RECOMMENDATION: You should create a restricted volume where nobody can read/write files, and make sure that all IdP volumes are configured to appear somewhere below that volume."
|
2563
2602
|
self.log(t + "".join(self.idp_err), 1)
|
2564
2603
|
|
2604
|
+
if have_reflink:
|
2605
|
+
t = "WARNING: Reflink-based dedup was requested, but %s. This will not work; files will be full copies instead."
|
2606
|
+
if sys.version_info < (3, 14):
|
2607
|
+
self.log(t % "your python version is not new enough", 1)
|
2608
|
+
if not sys.platform.startswith("linux"):
|
2609
|
+
self.log(t % "your OS is not Linux", 1)
|
2610
|
+
|
2565
2611
|
self.vfs = vfs
|
2566
2612
|
self.acct = acct
|
2567
2613
|
self.defpw = defpw
|
@@ -2731,7 +2777,7 @@ class AuthSrv(object):
|
|
2731
2777
|
"lifetime": vn.js_ls["lifetime"],
|
2732
2778
|
"u2sort": self.args.u2sort,
|
2733
2779
|
}
|
2734
|
-
vn.js_htm = json.dumps(js_htm)
|
2780
|
+
vn.js_htm = json_hesc(json.dumps(js_htm))
|
2735
2781
|
|
2736
2782
|
vols = list(vfs.all_nodes.values())
|
2737
2783
|
if enshare:
|
@@ -6,8 +6,11 @@ import os
|
|
6
6
|
from ..util import SYMTIME, fsdec, fsenc
|
7
7
|
from . import path as path
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
MKD_755 = {"chmod_d": 0o755}
|
10
|
+
MKD_700 = {"chmod_d": 0o700}
|
11
|
+
|
12
|
+
_ = (path, MKD_755, MKD_700)
|
13
|
+
__all__ = ["path", "MKD_755", "MKD_700"]
|
11
14
|
|
12
15
|
# grep -hRiE '(^|[^a-zA-Z_\.-])os\.' . | gsed -r 's/ /\n/g;s/\(/(\n/g' | grep -hRiE '(^|[^a-zA-Z_\.-])os\.' | sort | uniq -c
|
13
16
|
# printf 'os\.(%s)' "$(grep ^def bos/__init__.py | gsed -r 's/^def //;s/\(.*//' | tr '\n' '|' | gsed -r 's/.$//')"
|
@@ -17,11 +20,15 @@ def chmod(p , mode ) :
|
|
17
20
|
return os.chmod(fsenc(p), mode)
|
18
21
|
|
19
22
|
|
23
|
+
def chown(p , uid , gid ) :
|
24
|
+
return os.chown(fsenc(p), uid, gid)
|
25
|
+
|
26
|
+
|
20
27
|
def listdir(p = ".") :
|
21
28
|
return [fsdec(x) for x in os.listdir(fsenc(p))]
|
22
29
|
|
23
30
|
|
24
|
-
def makedirs(name ,
|
31
|
+
def makedirs(name , vf = MKD_755, exist_ok = True) :
|
25
32
|
# os.makedirs does 777 for all but leaf; this does mode on all
|
26
33
|
todo = []
|
27
34
|
bname = fsenc(name)
|
@@ -34,9 +41,13 @@ def makedirs(name , mode = 0o755, exist_ok = True) :
|
|
34
41
|
if not exist_ok:
|
35
42
|
os.mkdir(bname) # to throw
|
36
43
|
return False
|
44
|
+
mode = vf["chmod_d"]
|
45
|
+
chown = "chown" in vf
|
37
46
|
for zb in todo[::-1]:
|
38
47
|
try:
|
39
48
|
os.mkdir(zb, mode)
|
49
|
+
if chown:
|
50
|
+
os.chown(zb, vf["uid"], vf["gid"])
|
40
51
|
except:
|
41
52
|
if os.path.isdir(zb):
|
42
53
|
continue
|
@@ -52,6 +52,7 @@ def vf_bmap() :
|
|
52
52
|
"og_no_head",
|
53
53
|
"og_s_title",
|
54
54
|
"rand",
|
55
|
+
"reflink",
|
55
56
|
"rmagic",
|
56
57
|
"rss",
|
57
58
|
"wo_up_readme",
|
@@ -113,6 +114,8 @@ def vf_vmap() :
|
|
113
114
|
"unlist",
|
114
115
|
"u2abort",
|
115
116
|
"u2ts",
|
117
|
+
"uid",
|
118
|
+
"gid",
|
116
119
|
"ups_who",
|
117
120
|
"zip_who",
|
118
121
|
"zipmaxn",
|
@@ -168,11 +171,14 @@ flagcats = {
|
|
168
171
|
"dedup": "enable symlink-based file deduplication",
|
169
172
|
"hardlink": "enable hardlink-based file deduplication,\nwith fallback on symlinks when that is impossible",
|
170
173
|
"hardlinkonly": "dedup with hardlink only, never symlink;\nmake a full copy if hardlink is impossible",
|
174
|
+
"reflink": "enable reflink-based file deduplication,\nwith fallback on full copy when that is impossible",
|
171
175
|
"safededup": "verify on-disk data before using it for dedup",
|
172
176
|
"noclone": "take dupe data from clients, even if available on HDD",
|
173
177
|
"nodupe": "rejects existing files (instead of linking/cloning them)",
|
174
178
|
"chmod_d=755": "unix-permission for new dirs/folders",
|
175
179
|
"chmod_f=644": "unix-permission for new files",
|
180
|
+
"uid=573": "change owner of new files/folders to unix-user 573",
|
181
|
+
"gid=999": "change owner of new files/folders to unix-group 999",
|
176
182
|
"sparse": "force use of sparse files, mainly for s3-backed storage",
|
177
183
|
"nosparse": "deny use of sparse files, mainly for slow storage",
|
178
184
|
"daw": "enable full WebDAV write support (dangerous);\nPUT-operations will now \033[1;31mOVERWRITE\033[0;35m existing files",
|
@@ -31,6 +31,7 @@ from .util import (
|
|
31
31
|
relchk,
|
32
32
|
runhook,
|
33
33
|
sanitize_fn,
|
34
|
+
set_fperms,
|
34
35
|
vjoin,
|
35
36
|
wunlink,
|
36
37
|
)
|
@@ -258,8 +259,8 @@ class FtpFs(AbstractedFS):
|
|
258
259
|
wunlink(self.log, ap, VF_CAREFUL)
|
259
260
|
|
260
261
|
ret = open(fsenc(ap), mode, self.args.iobuf)
|
261
|
-
if w and "
|
262
|
-
|
262
|
+
if w and "fperms" in vfs.flags:
|
263
|
+
set_fperms(ret, vfs.flags)
|
263
264
|
|
264
265
|
return ret
|
265
266
|
|
@@ -293,8 +294,7 @@ class FtpFs(AbstractedFS):
|
|
293
294
|
|
294
295
|
def mkdir(self, path ) :
|
295
296
|
ap, vfs, _ = self.rv2a(path, w=True)
|
296
|
-
|
297
|
-
bos.makedirs(ap, chmod) # filezilla expects this
|
297
|
+
bos.makedirs(ap, vf=vfs.flags) # filezilla expects this
|
298
298
|
|
299
299
|
def listdir(self, path ) :
|
300
300
|
vpath = join(self.cwd, path)
|