summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Fankhauser hiddenalpha.ch2023-01-17 11:01:25 +0100
committerAndreas Fankhauser hiddenalpha.ch2023-01-17 11:01:25 +0100
commitb55452aca69ea85d5f8be9f1926c46b3d72ce4ff (patch)
tree2c8111fa60900aa1f60f92fda20a86a3529a4bb9
parent91627b0ec1ceeb9521e351381aa6b585573e630a (diff)
parent41a0f97bafb3d95cfd9f05fd11b01adf8ac62e50 (diff)
downloadUnspecifiedGarbage-b55452aca69ea85d5f8be9f1926c46b3d72ce4ff.zip
UnspecifiedGarbage-b55452aca69ea85d5f8be9f1926c46b3d72ce4ff.tar.gz
Merge branch 'master' into wip-MvnDepScan-20221207
-rw-r--r--LICENSE.txt14
-rw-r--r--doc/note/cross-compile/CrossCompile.txt8
-rw-r--r--doc/note/docker/Docker.txt11
-rw-r--r--doc/note/ffmpeg/ffmpeg.txt15
-rw-r--r--doc/note/gpg/gpg.txt82
-rw-r--r--doc/note/links/links.txt33
-rw-r--r--doc/note/maven-pom/base.xml34
-rw-r--r--doc/note/ssh/_SeeAlsoTls0
-rw-r--r--doc/note/tls/_SeeAlsoSsh0
-rw-r--r--doc/note/tls/tls.txt34
-rw-r--r--src/main/docker/gcc-windoof.Dockerfile (renamed from src/main/docker/windoof-gcc.Dockerfile)0
-rw-r--r--src/main/docker/gcc.Dockerfile (renamed from src/main/docker/debian-gcc.Dockerfile)0
-rw-r--r--src/main/docker/gxx.Dockerfile (renamed from src/main/docker/debian-cxx.Dockerfile)0
-rw-r--r--src/main/docker/jni.Dockerfile (renamed from src/main/docker/debian-jni.Dockerfile)0
-rw-r--r--src/main/docker/jre8.Dockerfile (renamed from src/main/docker/alpine-jre8.Dockerfile)0
-rw-r--r--src/main/docker/maven.Dockerfile (renamed from src/main/docker/alpine-mvn.Dockerfile)9
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java6
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java54
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java8
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java8
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java8
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java4
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java30
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java8
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java9
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java15
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java26
-rw-r--r--src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java57
-rwxr-xr-xsrc/main/shell/BackupByRsync/backup.sh137
29 files changed, 476 insertions, 134 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..b9e20aa
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,14 @@
+
+Copyright (c) 2022 Andreas Fankhauser
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/doc/note/cross-compile/CrossCompile.txt b/doc/note/cross-compile/CrossCompile.txt
new file mode 100644
index 0000000..5341164
--- /dev/null
+++ b/doc/note/cross-compile/CrossCompile.txt
@@ -0,0 +1,8 @@
+
+Cross Compilation & Portability
+===============================
+
+10 most essential rules for portable C code:
+
+ https://www.ski-epic.com/source_code_essays/ten_rules_for_writing_cross_platform_c_source_code.html
+
diff --git a/doc/note/docker/Docker.txt b/doc/note/docker/Docker.txt
index 7a9d130..ac283c9 100644
--- a/doc/note/docker/Docker.txt
+++ b/doc/note/docker/Docker.txt
@@ -57,6 +57,17 @@ Side-Mount tcpdump into container where it does not exist
docker run --rm -ti --network container:"${CNTNR_TO_DUMP:?}" -v "/tmp/foo:/work" "${IMG_WITH_TCPDUMP_EG_BASEIMG:?}" bash
+## Inspect failing docker-build
+
+See "https://stackoverflow.com/a/26222636/4415884"
+
+ docker run --rm -ti 42424242 sh
+
+HINT: Use the line which looks like:
+"---> 42424242"
+and NOT the one like:
+"---> Running in 42424242"
+
## Publish custom images to artifactory
diff --git a/doc/note/ffmpeg/ffmpeg.txt b/doc/note/ffmpeg/ffmpeg.txt
index 9d95bfd..057c11d 100644
--- a/doc/note/ffmpeg/ffmpeg.txt
+++ b/doc/note/ffmpeg/ffmpeg.txt
@@ -2,7 +2,6 @@
ffmpeg
================
-j
## Extract Audio From webm
Lookup format of audio stream with:
@@ -17,9 +16,21 @@ Then use that knowlege to extract that (audio) stream:
## Convert Formats
-ffmpeg -i in.opus out.wav
+ ffmpeg -i in.opus out.wav
+## Fine-tune audio codec
+
+[See also](https://slhck.info/video/2017/02/24/vbr-settings.html)
+
+Use -codec:v copy to keep video, or -codec:v no for audio-only.
+
+ -codec:a aac -q:a 1.3 (min=0.1, good=1.3 max=2)
+ -codec:a aac -b:a 96k
+ -codec:a libmp3lame -q:a 2
+ -codec:a libopus
+ -filter:a lowpass=f=16000
+
## Record Desktop
diff --git a/doc/note/gpg/gpg.txt b/doc/note/gpg/gpg.txt
new file mode 100644
index 0000000..015887c
--- /dev/null
+++ b/doc/note/gpg/gpg.txt
@@ -0,0 +1,82 @@
+
+How to GnuPG
+============
+
+WARN: You MUST only use those instructions if you know exactly what
+you're doing! If you don't, you MUST NOT use those instructions!
+
+
+## Prepare for a master key creation
+
+- Choose a storage medium which will keep the master key and will be
+ kept VERY SAVE somewhere (also think for some redundancy). WARN: If
+ you choose a medium which probably could fail, you will be screwed up
+ in a later point in time!
+- Choose how (or where?) to keep master passphrase.
+
+
+## Initialize a new master key
+
+ export GNUPGHOME=/mnt/your/master/.gnupg
+ gpg --full-gen-key
+
+
+## Add additional identities (as needed)
+
+ export GNUPGHOME=/mnt/your/master/.gnupg
+ gpg --edit-key foo@example.com
+ gpg> adduid
+ gpg> save
+
+
+## Create keys for some daily-use devices
+
+ export GNUPGHOME=/mnt/your/master/.gnupg
+ gpg --edit-key foo@example.com
+ # Add an encryption and a sign key
+ gpg> addkey (then choose "encryp only")
+ gpg> addkey (then choose "sign only")
+
+
+## Export subkeys for use on a daily-use device
+
+ # From now work with a temporary copy.
+ mkdir /mnt/your/tmp/.gnupg
+ (cd /mnt/your/master/.gnupg && tar c $(ls -A)) | (cd /mnt/your/tmp/.gnupg && tar x)
+ export GNUPGHOME=/mnt/your/tmp/.gnupg
+ # Print list of what we have
+ gpg --edit-key foo@example.com quit
+ # I suggest to use a different passphrase than the master key has.
+ # (HINT: just ignore error about missing private key. it works anyway)
+ gpg --edit-key foo@example.com passwd quit
+ # For each device choose one encrypt and one sign key and replace F00 and BA5
+ # below with them.
+ gpg --export-secret-subkeys F00! BA5! > keys-for-device
+
+
+## Import prepared subkeys on daily-use device
+
+ gpg --import keys-for-device
+ gpg --edit-key foo@example.com
+ gpg> trust
+ gpg> save
+
+
+## Sign a foreign key to express to the world that we trust it
+
+ gpgwin --sign-key foreignUser@example.com
+
+
+## Some other helpful places
+
+- "https://insight.o-o.studio/article/setting-up-gpg.html#encryption-key"
+- "https://davesteele.github.io/gpg/2014/09/20/anatomy-of-a-gpg-key/"
+- "https://gpg.wtf/"
+
+
+## Start/stop gpg-agent
+
+ gpgconf --kill gpg-agent
+ gpgconf --launch gpg-agent
+
+
diff --git a/doc/note/links/links.txt b/doc/note/links/links.txt
index 3ca26ba..af41581 100644
--- a/doc/note/links/links.txt
+++ b/doc/note/links/links.txt
@@ -1,5 +1,5 @@
-Links (Aka arguments)
+Links (Aka argument amplifiers)
=====================
## Pro DI over serviceLocator
@@ -82,7 +82,7 @@ Links (Aka arguments)
- SRP "https://blog.ndepend.com/solid-design-the-single-responsibility-principle-srp/"
- OCP "https://blog.ndepend.com/solid-design-the-open-close-principle-ocp/"
- LSP "https://blog.ndepend.com/solid-design-the-liskov-substitution-principle/"
-- DIP "https://stackify.com/dependency-inversion-principle/"
+- DIP "https://stackify.com/dependency-inversion-principle/#post-18184-_nuqaxpnmvpn7"
## Java how to handle InterruptedException:
- "https://www.yegor256.com/2015/10/20/interrupted-exception.html"
@@ -121,7 +121,7 @@ Links (Aka arguments)
## Why I Have Given Up On Coding Standards
- "http://www.richardrodger.com/2012/11/03/why-i-have-given-up-on-coding-standards/"
-## slf4j logger dos and donts0
+## slf4j logger dos and donts
- [case SO](https://stackoverflow.com/questions/1417190/should-a-static-final-logger-be-declared-in-upper-case)
- [case java-styleguide](https://web.archive.org/web/20120911192801if_/http://developers.sun.com/sunstudio/products/archive/whitepapers/java-style.pdf#G3.5426)
- [case slf4j](http://www.slf4j.org/api/org/slf4j/Logger.html)
@@ -148,10 +148,13 @@ Links (Aka arguments)
- "https://gitit.post.ch/projects/ISA/repos/zarquon/pull-requests/2/overview?commentId=61312"
## Code Style format auto-formatters
+- [warning about formatters](https://gitit.post.ch/projects/ISA/repos/trin/pull-requests/79/overview?commentId=235667)
- [static final java uppercase](https://gitit.post.ch/projects/ISA/repos/preflux/pull-requests/82/overview?commentId=39126)
- [invalid java class name](https://gitit.post.ch/projects/ISA/repos/preflux/pull-requests/82/overview?commentId=39125)
-- [Formatters produce crap](https://gitit.post.ch/projects/ISA/repos/minetti/pull-requests/14/overview)
-- [Formatters produce crap](https://gitit.post.ch/projects/ISA/repos/veet/pull-requests/2/overview?commentId=233638)
+- [Spotless produces crap](https://gitit.post.ch/projects/ISA/repos/minetti/pull-requests/14/overview)
+- [Spotless produces crap](https://gitit.post.ch/projects/ISA/repos/veet/pull-requests/2/overview?commentId=233638)
+- [Spotless produces crap](https://gitit.post.ch/projects/ISA/repos/trin/pull-requests/79)
+- [Linter produces crap](https://gitit.post.ch/projects/ISA/repos/preflux/pull-requests/567/overview?commentId=237627)
- [Suddenly NEW formatting rules in PaISA since 2021](https://gitit.post.ch/projects/ISA/repos/watson/pull-requests/1/overview?commentId=234597)
- "https://gitit.post.ch/projects/ISA/repos/zarniwoop/pull-requests/20/overview?commentId=85912"
- "https://gitit.post.ch/projects/ISA/repos/zarniwoop/pull-requests/21/overview?commentId=87250"
@@ -299,6 +302,7 @@ Links (Aka arguments)
## Command Escaping And Injection
- "https://jira.post.ch/browse/SDCISA-3602"
+- [My hopefully bullet-proove shell escaping](https://gitit.post.ch/projects/ISA/repos/jenkins-shared-libraries/pull-requests/82/overview?commentId=237165)
## logger noise spam verbose
- [fix the REAL problem please](https://jira.post.ch/browse/SDCISA-3637?focusedCommentId=1252741&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-1252741)
@@ -310,6 +314,7 @@ Links (Aka arguments)
## YAGNI (but also KISS and DRY)
- "https://medium.com/swlh/yagni-and-dry-the-kiss-of-death-for-your-software-project-cfd44b0654b6#fc82"
+- [eagle queue json only](https://gitit.post.ch/projects/ISA/repos/eagle/pull-requests/331/overview?commentId=236944)
## How to format method parameters
- "https://gitit.post.ch/projects/ISA/repos/god-backend/pull-requests/281/overview?commentId=210650"
@@ -409,3 +414,21 @@ Links (Aka arguments)
## Encoding mime application/octet-stream string utf8 unicode json payload data
- [eagle queue browser](https://gitit.post.ch/projects/ISA/repos/eagle/pull-requests/331/overview?commentId=232322)
+## Stop using that stupid mouse! For some reason you've got a keyboard
+- [_](https://www.vice.com/en/article/d3m8ga/i-stopped-using-a-computer-mouse-for-a-week)
+- [_](https://medium.com/ae-studio/save-a-month-of-your-life-by-using-these-keyboard-shortcuts-a07fdba5dc6e)
+- [_](https://blog.superhuman.com/keyboard-vs-mouse/)
+
+## How to get real InputStream from RestTemplate
+- [java spring http web InputStream RestTemplate body](https://stackoverflow.com/a/62649586/4415884)
+
+## Stone age deprecated obsolete for years
+- [API using naming deprecated for 7 years](https://gitit.post.ch/projects/ISA/repos/notifications-api/pull-requests/7/overview?commentId=238160)
+
+## ImageMagic
+- [Bulk resize pictures](https://stackoverflow.com/questions/36986436/how-to-batch-resize-millions-of-images-to-fit-a-max-width-and-height)
+- [mogrify bulk changes](https://www.lostsaloon.com/technology/resize-multiple-images-batch-command-line-linux/)
+
+## Windoof
+- [Enable w32 crashdump](https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps?source=recommendations)
+
diff --git a/doc/note/maven-pom/base.xml b/doc/note/maven-pom/base.xml
new file mode 100644
index 0000000..68624fb
--- /dev/null
+++ b/doc/note/maven-pom/base.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>TODO</groupId>
+ <artifactId>TODO</artifactId>
+ <version>0.0.0-SNAPSHOT</version>
+
+ <!-- <parent> -->
+ <!-- <groupId>TODO</groupId> -->
+ <!-- <artifactId>TODO</artifactId> -->
+ <!-- <version>TODO</version> -->
+ <!-- </parent> -->
+
+ <!-- <packaging>Choose: jar, pom, war</packaging> -->
+
+ <!-- <properties> -->
+ <!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> -->
+ <!-- <maven.compiler.source>8</maven.compiler.source> -->
+ <!-- <maven.compiler.target>8</maven.compiler.target> -->
+ <!-- </properties> -->
+
+ <!-- <dependencies> -->
+ <!-- </dependencies> -->
+
+ <!-- <dependencyManagement> -->
+ <!-- <dependencies> -->
+ <!-- </dependencies> -->
+ <!-- </dependencyManagement> -->
+
+</project>
diff --git a/doc/note/ssh/_SeeAlsoTls b/doc/note/ssh/_SeeAlsoTls
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/note/ssh/_SeeAlsoTls
diff --git a/doc/note/tls/_SeeAlsoSsh b/doc/note/tls/_SeeAlsoSsh
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/note/tls/_SeeAlsoSsh
diff --git a/doc/note/tls/tls.txt b/doc/note/tls/tls.txt
new file mode 100644
index 0000000..ce1e305
--- /dev/null
+++ b/doc/note/tls/tls.txt
@@ -0,0 +1,34 @@
+
+TLS Key Management
+==================
+
+WARN: Nothing useful here. Just some nonsense copy-pasta lines.
+
+
+## Create new server PEM cert
+
+```sh
+openssl genrsa -out path/to/private/key 2048
+```
+
+```sh
+openssl req -new -key path/to/private/key -new -nodes -x509 -days 42 -out path/to/certSignRequest.csr -subj "/C=/ST=/L=/O=/OU=/CN=example.com"
+```
+
+```sh
+openssl x509 -req -days 42 -in path/to/certSignRequest.csr -signkey path/to/private/key -out path/to/cert.crt
+```
+
+```sh
+cat path/to/private/key path/to/cert.crt > path/to/cert.pem
+```
+
+
+## TLS debugging
+
+```sh
+socat OPENSSL-LISTEN:1234,reuseaddr,cert=server.pem tcp-connect:127.0.0.1:1235
+```
+
+HINT: Add option 'fork' to ssl sock to serve multiple requests.
+
diff --git a/src/main/docker/windoof-gcc.Dockerfile b/src/main/docker/gcc-windoof.Dockerfile
index 69cc18e..69cc18e 100644
--- a/src/main/docker/windoof-gcc.Dockerfile
+++ b/src/main/docker/gcc-windoof.Dockerfile
diff --git a/src/main/docker/debian-gcc.Dockerfile b/src/main/docker/gcc.Dockerfile
index 5894667..5894667 100644
--- a/src/main/docker/debian-gcc.Dockerfile
+++ b/src/main/docker/gcc.Dockerfile
diff --git a/src/main/docker/debian-cxx.Dockerfile b/src/main/docker/gxx.Dockerfile
index f29f168..f29f168 100644
--- a/src/main/docker/debian-cxx.Dockerfile
+++ b/src/main/docker/gxx.Dockerfile
diff --git a/src/main/docker/debian-jni.Dockerfile b/src/main/docker/jni.Dockerfile
index c790e47..c790e47 100644
--- a/src/main/docker/debian-jni.Dockerfile
+++ b/src/main/docker/jni.Dockerfile
diff --git a/src/main/docker/alpine-jre8.Dockerfile b/src/main/docker/jre8.Dockerfile
index 603b5f5..603b5f5 100644
--- a/src/main/docker/alpine-jre8.Dockerfile
+++ b/src/main/docker/jre8.Dockerfile
diff --git a/src/main/docker/alpine-mvn.Dockerfile b/src/main/docker/maven.Dockerfile
index e6c68f9..c33d519 100644
--- a/src/main/docker/alpine-mvn.Dockerfile
+++ b/src/main/docker/maven.Dockerfile
@@ -1,12 +1,9 @@
#
# Maven build env.
#
-# Make sure to use arg
+# Use this to share your hosts repository with the container:
#
-# -v "$HOME/.m2/repo:/data/maven/.m2/repo"
-#
-# so it can use your hosts artifacts cache. If you miss this, mvn has to
-# download all the dependencies from remote uselessly often.
+# -v "$HOME/.m2/repository:/data/maven/.m2/repository"
#
ARG PARENT_IMAGE=alpine:3.16.0
@@ -24,7 +21,7 @@ WORKDIR /work
RUN true \
&& $PKGINIT \
&& $PKGADD $PKGS_TO_ADD \
- && sed -i "s,</settings>, <localRepository>/data/maven/.m2/repo</localRepository>\n</settings>,g" /usr/share/java/maven-3/conf/settings.xml \
+ && sed -i "s,</settings>, <localRepository>/data/maven/.m2/repository</localRepository>\n</settings>,g" /usr/share/java/maven-3/conf/settings.xml \
&& mkdir /data /data/maven \
&& chown 1000:1000 /data/maven \
&& chown 1000:1000 /work \
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java
index a75594f..415090f 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/collection/CollectionUtils.java
@@ -13,9 +13,9 @@ public class CollectionUtils {
* @param <T>
* Type of the elements we are working with.
*/
- public static <T> boolean contains(T[] haystack, T needle, java.util.function.BiPredicate<T, T> equals) {
- for (T t : haystack) {
- if (equals.test(needle, t)) {
+ public static <T> boolean contains( T[] haystack, T needle, java.util.function.BiPredicate<T, T> equals ){
+ for( T t : haystack ){
+ if( equals.test(needle, t) ){
return true;
}
}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java
index bd39e40..e156eb8 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/format/FormatUtils.java
@@ -1,54 +1,6 @@
package ch.hiddenalpha.unspecifiedgarbage.format;
-public class FormatUtils {
-
- /**
- * Tries to format 'val' as a small integer. If not possible falls back
- * to decimal representation. If also not possible, falls back to scientific
- * notation.
- *
- * Handy in cases where we need to "just print that number" without having
- * stupid amount of nonsense decimal places or bother readers with
- * scientific notation where "just an int" would perfectly do the job.
- *
- * @param val
- * The number to format.
- *
- * @param ndig
- * How many significant digits to be printed. MUST be in range 1..7.
- */
- public static String toStr(float val, int ndig) {
- int exp;
- float limit;
- if (val == 0) return "0";
- switch (ndig) {
- case 1: exp = 1; limit = 1e4F; break;
- case 2: exp = 10; limit = 1e6F; break;
- case 3: exp = 100; limit = 1e7F; break;
- case 4: exp = 1000; limit = 1e8F; break;
- case 5: exp = 10000; limit = 1e9F; break;
- case 6: exp = 100000; limit = 1e10F; break;
- case 7: exp = 1000000; limit = 1e11F; break;
- default: throw new IllegalArgumentException("ndig " + ndig + " not in expected range 1..7");
- }
- if (val >= exp && val <= limit) {
- // Just print as an int.
- return String.valueOf((int) val);
- } else {
- String fmt;
- switch (ndig) { // Select an appropriate format.
- case 1: fmt = "%.1g"; break;
- case 2: fmt = "%.2g"; break;
- case 3: fmt = "%.3g"; break;
- case 4: fmt = "%.4g"; break;
- case 5: fmt = "%.5g"; break;
- case 6: fmt = "%.6g"; break;
- case 7: fmt = "%.7g"; break;
- default: throw new IllegalArgumentException("ndig " + ndig + " not in expected range 1..7");
- }
- return String.format(fmt, val).replace(',', '.').replace("'", "");
- }
- }
-
-}
+/** Obsolete: This class did migrate to "xtra4j" */
+@Deprecated
+public class FormatUtils {}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java
index c8be86a..f860b85 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/json/JsonUtils.java
@@ -24,18 +24,18 @@ public class JsonUtils {
*/
public static
<TreeToValueFunc extends ObjectCodecIface<JsonNode, Map>, JsonNode, K, V>
- Map<K, V> decodeMap(TreeToValueFunc treeToValueFunc, JsonNode mapNode, Class<K> keyType, Class<V> valueType) throws IOException {
+ Map<K, V> decodeMap( TreeToValueFunc treeToValueFunc, JsonNode mapNode, Class<K> keyType, Class<V> valueType ) throws IOException {
final Map<K, V> envVars;
- if (mapNode == null) {
+ if( mapNode == null ){
envVars = new LinkedHashMap<>();
- } else {
+ }else{
envVars = treeToValueFunc.treeToValue(mapNode, Map.class);
}
return envVars;
}
public static interface ObjectCodecIface<TreeNode, Value> {
- Value treeToValue(TreeNode input, Class<Map> returnType) throws IOException;
+ Value treeToValue( TreeNode input, Class<Map> returnType ) throws IOException;
}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java
index 04688d6..49959fc 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteChunkOStream.java
@@ -38,8 +38,8 @@ public class ByteChunkOStream extends OutputStream {
len -= appendedBytes;
}else if( remainingBytes == 0 ){
break; // Done :)
- }else {
- throw new UnsupportedOperationException("Huh?!? why is remainingBytes " + remainingBytes + "?");
+ }else{
+ throw new UnsupportedOperationException("Huh?!? why is remainingBytes "+ remainingBytes +"?");
}
}
}
@@ -117,11 +117,11 @@ public class ByteChunkOStream extends OutputStream {
/** Inspired by {@link java.util.function.Consumer} */
public static interface ChunkHandler {
- void accept(byte[] bytes) throws IOException;
+ void accept( byte[] bytes ) throws IOException;
}
- /** Inspired by {@link Runnable#run()} */
+ /** Inspired by {@link java.util.function.Runnable#run()} */
public static interface EndHandler {
void run() throws IOException;
}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java
index 006ea6b..8e2b47f 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ByteCountOutputStream.java
@@ -31,13 +31,9 @@ public class ByteCountOutputStream extends OutputStream {
}
@Override
- public void flush() throws IOException {
- origin.flush();
- }
+ public void flush() throws IOException { origin.flush(); }
@Override
- public void close() throws IOException {
- origin.close();
- }
+ public void close() throws IOException { origin.close(); }
}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java
index 4a619da..b6c8131 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/BytePool.java
@@ -91,7 +91,7 @@ public class BytePool {
long amountLong = oldVal - newVal;
this.amount.set((int) amountLong);
if( this.amount.get() != amountLong ){
- throw new RuntimeException("A moron just tried to allocate " + amountLong + " bytes (more than INT_MAX)");
+ throw new RuntimeException("A moron just tried to allocate "+ amountLong +" bytes (more than INT_MAX)");
}
}
@@ -107,7 +107,7 @@ public class BytePool {
* // Don't know exactly how much we need. Make a guess.<br/>
* allocdBytes = pool.alloc(42);<br/>
* int actuallyNeeded = source.read(buf, 0, allocdBytes.getAmount());<br/>
- * // Now we know exactly how much we need and can free the rest.<br/>
+ * // Now we know exactly how much we need and can release the rest.<br/>
* allocdBytes.shrinkTo(actuallyNeeded);<br/>
* </code>
*/
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java
index 75b1a9f..0c242aa 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CRLFtoLFOutputStream.java
@@ -4,13 +4,15 @@ import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import org.slf4j.ILoggerFactory;
+import org.slf4j.Logger;
-/**
- * Filter to fix broken newlines.
- */
+
+/** Filters away broken newlines. */
public class CRLFtoLFOutputStream extends FilterOutputStream {
private static final int EMPTY = -42;
+ private final Logger log;
private int previous = EMPTY;
/**
@@ -18,7 +20,16 @@ public class CRLFtoLFOutputStream extends FilterOutputStream {
* Destination where the result will be written to.
*/
public CRLFtoLFOutputStream( OutputStream dst ) {
+ this(dst, null);
+ }
+
+ /**
+ * @param dst
+ * Destination where the result will be written to.
+ */
+ public CRLFtoLFOutputStream( OutputStream dst, ILoggerFactory lf ) {
super(dst);
+ this.log = (lf == null) ? null : lf.getLogger(CRLFtoLFOutputStream.class.getName());
}
@Override
@@ -27,7 +38,7 @@ public class CRLFtoLFOutputStream extends FilterOutputStream {
// This allows us to assign special meanings to those values internally (eg our
// 'EMPTY' value). For this to work, we clear the high bits to not get confused
// just in case someone really passes such values.
- current = current & 0xFF;
+ current &= 0xFF;
if( previous == '\r' && current == '\n' ){
// Ignore the CR and only write the LF.
@@ -43,14 +54,21 @@ public class CRLFtoLFOutputStream extends FilterOutputStream {
}
}
+ // TODO we should override this.
+ //@Override
+ //public void write( byte[] buf, int off, int len ) throws IOException {
+ // throw new UnsupportedOperationException("TODO impl");/*TODO*/
+ //}
+
@Override
public void flush() throws IOException {
if( previous == '\r' ){
- //log.warn("Have to flush a CR byte without knowing if the next byte might be a LF");
+ log.debug("Have to flush a CR byte without knowing if the next byte might be a LF");
}
if( previous != EMPTY ){
- super.write(previous);
+ int tmp = previous;
previous = EMPTY;
+ super.write(tmp);
}
super.flush();
}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java
index 2e19c52..a8d6eea 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/CloseNotifyOutputStream.java
@@ -17,9 +17,9 @@ public class CloseNotifyOutputStream extends FilterOutputStream {
private final Runnable onClose;
private final AtomicBoolean isFired = new AtomicBoolean(false);
- public CloseNotifyOutputStream(OutputStream out, Runnable onClose) {
+ public CloseNotifyOutputStream( OutputStream out, Runnable onClose ){
super(out);
- if(true) throw new UnsupportedOperationException("TODO need to delegate close call");/*TODO*/
+ if( true ) throw new UnsupportedOperationException("TODO need to delegate close call");/*TODO*/
this.onClose = requireNonNull(onClose);
}
@@ -28,6 +28,10 @@ public class CloseNotifyOutputStream extends FilterOutputStream {
if (!isFired.getAndSet(true)) {
onClose.run();
}
+ // TODO Need to delegate to filtered stream.
+ // Properly delegating requires to propery handle all the
+ // special cases around exceptions. See also
+ // CloseNotifyInputStream which does a similar task.
}
}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java
index 819e6da..8c89fc0 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/octetstream/ConcatInputStream.java
@@ -57,12 +57,13 @@ public class ConcatInputStream extends InputStream {
public void close() throws IOException {
// Close all remaining sources.
Exception firstException = null;
- for( int i = iSrc; i < sources.length; ++i ){
+ for( int i = iSrc ; i < sources.length ; ++i ){
try{
sources[i].close();
}catch( IOException|RuntimeException ex ){
if( firstException == null ){
- // Track the exception. But we need to close the remaining ones.
+ // Track the exception. But we have to close the
+ // remaining streams regardless of early exceptions.
firstException = ex;
}else if( firstException != ex ){
firstException.addSuppressed(ex);
@@ -72,7 +73,7 @@ public class ConcatInputStream extends InputStream {
sources = null; // Allow GC
// Bubble exception if we had any.
if( firstException instanceof RuntimeException ){
- throw (RuntimeException) firstException;
+ throw (RuntimeException)firstException;
}else if( firstException != null ){
throw (IOException)firstException;
}
@@ -83,6 +84,8 @@ public class ConcatInputStream extends InputStream {
InputStream oldSrc = sources[iSrc];
sources[iSrc] = null;
iSrc += 1;
+ // Calling close as last step to prevent trouble with our
+ // state as it potentially could throw.
oldSrc.close();
}
}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java
index 5e2aff2..6c903ec 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/shell/ShellUtils.java
@@ -6,10 +6,13 @@ public class ShellUtils {
/**
* Escapes the string so we can use the result in a
* <a href="https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_02_03">double-quoted shell string</a>.
- * But keeps <a href="https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02">parameter expansion</a> alive.
+ * But keeps <a href="https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02">parameter expansion</a>
+ * alive.
* Example usage:
- * String path = "pâth \\with ${varToResolve} but a|so €vil chars like spaces, p|pes or * asterisk";
- * cmd = "ls '"+ escapeForSnglQuotEverything(path) +"'";
+ * <code>
+ * String path = "pâth \\with ${varToResolve} but a|so €vil chars like spaces, p|pes or * asterisk";<br/>
+ * cmd = "ls \""+ escapeForDblQuotButParams(path) +"\"";<br/>
+ * </code>
*/
public static String escapeForDblQuotButParams( String s ){
s = s.replace("\\", "\\\\");
@@ -23,8 +26,10 @@ public class ShellUtils {
* Escapes the string so we can use result in a
* <a href="https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_02_02">single-quoted shell string</a>.
* Example usage:
- * String path = "pâth \\with ${MustNotResolveThisVar} and a|so €vil chars like spaces, p|pes or * asterisk";
- * cmd = "ls '"+ escapeForSnglQuotEverything(path) +"'";
+ * <code>
+ * String path = "pâth \\with ${MustNotResolveThisVar} and a|so €vil chars like spaces, p|pes or * asterisk";<br/>
+ * cmd = "ls '"+ escapeForSnglQuotEverything(path) +"'";<br/>
+ * </code>
*/
public static String escapeForSingleQuotEverything( String s ){
// Cited from "Single-Quotes" in "https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html":
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java
index 696d4d3..7d712ee 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/stream/StreamUtils.java
@@ -1,5 +1,8 @@
package ch.hiddenalpha.unspecifiedgarbage.stream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -11,28 +14,29 @@ public class StreamUtils {
/**
* Copies 'is' to 'os' until end of 'is' is reached. (Blocking)
+ *
+ * <p>BTW: Using this function makes no longer sense in projects using java
+ * 9 or later. Just use {@link java.io.InputStream#transferTo(java.io.OutputStream)}
+ * instead.</p>
+ *
* @return
* Count of copied bytes.
*/
- public static long copy(java.io.InputStream is, java.io.OutputStream os) throws java.io.IOException {
- byte[] buffer = new byte[1024];
+ public static long copy( java.io.InputStream is, java.io.OutputStream os ) throws java.io.IOException {
+ byte[] buffer = new byte[8192];
long totalBytes = 0;
int readLen;
while( -1 != (readLen=is.read(buffer,0,buffer.length)) ){
totalBytes += readLen;
- os.write( buffer , 0 , readLen );
+ os.write(buffer, 0, readLen);
}
return totalBytes;
}
- public static <SRC,DST> java.util.Iterator<DST> map(java.util.Iterator<SRC> src , java.util.function.Function<SRC,DST> mapper) {
+ public static <SRC,DST> java.util.Iterator<DST> map( java.util.Iterator<SRC> src , java.util.function.Function<SRC,DST> mapper ) {
return new Iterator<DST>() {
- @Override public boolean hasNext() {
- return src.hasNext();
- }
- @Override public DST next() {
- return mapper.apply(src.next());
- }
+ @Override public boolean hasNext() { return src.hasNext(); }
+ @Override public DST next() { return mapper.apply(src.next()); }
};
}
@@ -41,7 +45,7 @@ public class StreamUtils {
return t -> seen.add(keyExtractor.apply(t));
}
- public static <T> Predicate<T> not(Predicate<T> p){
+ public static <T> Predicate<T> not( Predicate<T> p ){
return e -> !p.test(e);
}
diff --git a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java
index ddb1c13..2bb1bfb 100644
--- a/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java
+++ b/src/main/java/ch/hiddenalpha/unspecifiedgarbage/time/TimeUtils.java
@@ -4,17 +4,17 @@ package ch.hiddenalpha.unspecifiedgarbage.time;
public class TimeUtils {
/**
- * Delegates to {@link #nanosToEpochMillis(long, long, long)} and assumes
- * that the 'nanos' value was measure in the same JVM process as this call
- * here occurs and is not too long back.
+ * Delegates to {@link #nanosToEpochMillis(long, long, long)} and
+ * assumes that the 'nanos' value was measured in the same JVM
+ * process as this call here occurs and is not too long back.
*/
- public static long nanosToEpochMillis(long nanos) {
+ public static long nanosToEpochMillis( long nanos ){
return nanosToEpochMillis(nanos, System.nanoTime(), System.currentTimeMillis());
}
- public static long nanosToEpochMillis(long nanos, long referenceNanos, long referenceEpochMs) {
+ public static long nanosToEpochMillis( long nanos, long referenceNanos, long referenceEpochMs ){
long diffNs = nanos - referenceNanos;
- if (diffNs < (Long.MIN_VALUE >> 1) || diffNs > (Long.MAX_VALUE>>1)) {
+ if( diffNs < (Long.MIN_VALUE >> 1) || diffNs > (Long.MAX_VALUE>>1) ){
// Looks as System.nanoTime() did overflow while measurement. So flip result too.
diffNs -= Long.MAX_VALUE;
}
@@ -22,29 +22,38 @@ public class TimeUtils {
}
/**
- * Computers cannot represent all existing integers. Due to how integers
- * are represented in computers, they are not infinite but more like a circle.
- * Speak when we infinitely increment an integer, it overflows and (usually)
- * continues to walk around this (imaginary) circle.
+ * Find smallest distance assuming integers overflow "like a circle".
*
- * This function takes two of those numbers on this circle and returns the
- * smallest distance to travel on the circle between them. Here some examples:
- * - f(7, 13) = 6
- * - f(-7, +11) = 18
- * - f(LONG_MIN, LONG_MAX) = 1
- * - f(-9223372036854775805, 9223372036854775802) = 9
+ * Computers cannot represent all existing integers. Due to how
+ * integers are represented in computers, they are not infinite but
+ * more like a circle. Speak when we infinitely increment an
+ * integer, it overflows and (usually) continues to walk around this
+ * (imaginary) circle.
+ *
+ * This function takes two of those numbers on this circle and
+ * returns the smallest distance to travel on the circle between
+ * them. Here some examples:
+ * <ul>
+ * <li>f(7, 13) = 6</li>
+ * <li>f(-7, +11) = 18</li>
+ * <li>f(LONG_MIN, LONG_MAX) = 1</li>
+ * <li>f(-9223372036854775805, 9223372036854775802) = 9</li>
+ * </ul>
*
* This can be handy for example in conjunction with {@link System#nanoTime()}.
- * Because in case of overflows between measuring begNs and endNs a simple subtraction
- * would lead to uselessly large results. So we can use it as:
- * long begNs = System.nanoTime();
- * long endNs = System.nanoTime();
- * long durationNs = nanosSmallDiff(begNs, endNs);
+ * Because in case of overflows between measuring begNs and endNs a
+ * simple subtraction would lead to uselessly large results. So we
+ * can use it as:
+ * <code>
+ * long begNs = System.nanoTime();
+ * long endNs = System.nanoTime();
+ * long durationNs = nanosSmallDiff(endNs, begNs);
+ * </code>
*
- * WARN: Do NOT use this if your distance can reach (LONG_MAX / 2). Because
- * in this case you would get wrong (too small) results.
+ * WARN: Do NOT use this if your distance can reach (LONG_MAX / 2).
+ * Because in this case you would get wrong (too small) results.
*/
- public static long nanosSmallDiff(long a, long b) {
+ public static long nanosSmallDiff( long a, long b ){
return (a - b >= 0) ? a - b : b - a;
}
diff --git a/src/main/shell/BackupByRsync/backup.sh b/src/main/shell/BackupByRsync/backup.sh
new file mode 100755
index 0000000..e557d45
--- /dev/null
+++ b/src/main/shell/BackupByRsync/backup.sh
@@ -0,0 +1,137 @@
+
+# Some tinkering about how I could do backup.
+#
+# Inspired by:
+# https://linuxconfig.org/how-to-create-incremental-backups-using-rsync-on-linux
+#
+# mount /dev/sdx1 /mnt/x
+#
+
+set -o errexit
+set -o pipefail
+
+readonly NOW_SHORT="$(date -u '+%Y%m%d-%H%M%S')"
+readonly DIR_FROM="/home/${USER:?}/."
+readonly DST_PREFIX="${DIR_FROM:?}"
+readonly DIR_TO="/mnt/x/ROOT_DIR/bkup-rsync/tux-six"
+readonly BACKUP_PATH="${DIR_TO}/${NOW_SHORT}"
+
+
+printHelp () {
+ printf "\n\
+ TODO write help page\n\
+ \n";
+}
+
+
+parseArgs () {
+ local arg0="$0"
+ local isExample="false"
+ while [ $# -gt 0 ]; do
+ local arg="$1"
+ if false; then
+ true
+ elif [ "$arg" == "--help" ]; then
+ printHelp; return 1
+ elif [ "$arg" == "--example" ]; then
+ isExample="true";
+ else
+ echo "Unexpected arg: $arg"; return 1
+ fi
+ shift 1
+ done
+ if ! $isExample; then echo >&2 "Bad args"; return 1; fi
+ return 0
+}
+
+
+run () {
+ if [ ! -e "${DIR_TO:?}" ]; then
+ echo >&2 "Backup root dir does not exist. Abort."
+ return 1
+ fi
+ mkdir -p "${BACKUP_PATH:?}/${DST_PREFIX:?}"
+ rsync --archive --verbose \
+ --link-dest "${DIR_TO}/latest/${DST_PREFIX:?}" \
+ --filter=':- .gitignore' \
+ --exclude=".git/COMMIT_EDITMSG" \
+ --exclude=".git/FETCH_HEAD" \
+ --exclude=".git/ORIG_HEAD" \
+ --exclude=".git/branches" \
+ --exclude=".git/hooks/*.sample" \
+ --exclude=".git/index" \
+ --exclude=".git/info" \
+ --exclude=".git/logs" \
+ --exclude=".git/objects" \
+ --exclude=".git/packed-refs" \
+ --exclude=".git/refs/remotes" \
+ --exclude=".git/refs/tags" \
+ --exclude=".idea" \
+ --exclude="/.NERDTreeBookmarks" \
+ --exclude="/.Xauthority" \
+ --exclude="/.bash_history" \
+ --exclude="/.config/VirtualBox/HostInterfaceNetworking-vboxnet0-Dhcpd.leases*" \
+ --exclude="/.config/VirtualBox/HostInterfaceNetworking-vboxnet0-Dhcpd.log*" \
+ --exclude="/.config/VirtualBox/VBoxSVC.log*" \
+ --exclude="/.config/VirtualBox/compreg.dat" \
+ --exclude="/.config/VirtualBox/selectorwindow.log*" \
+ --exclude="/.config/VirtualBox/vbox-ssl-cacertificate.crt" \
+ --exclude="/.config/VirtualBox/xpti.dat" \
+ --exclude="/.config/libreoffice" \
+ --exclude="/.config/GIMP" \
+ --exclude="/.config/JetBrains" \
+ --exclude="/.gdb_history" \
+ --exclude="/.lesshst" \
+ --exclude="/.profile" \
+ --exclude="/.vimrc" \
+ --exclude="/.xsession-errors" \
+ --exclude="/.xsession-errors.old" \
+ --exclude="/mnt" \
+ --exclude="/.android" \
+ --exclude="/.cache" \
+ --exclude="/.config/chromium" \
+ --exclude="/.config/inkscape" \
+ --exclude="/.local/share" \
+ --exclude="/.m2/repository" \
+ --exclude="/.mozilla/firefox" \
+ --exclude="/.squirrel-sql" \
+ --exclude="/.viking-maps" \
+ --exclude="/Downloads" \
+ --exclude="/crashdumps" \
+ --exclude="/images" \
+ --exclude="/projects/apple/cups" \
+ --exclude="/projects/gnu" \
+ --exclude="/projects/lua" \
+ --exclude="/projects/misc/OpenSSL" \
+ --exclude="/projects/misc/OpenVPN" \
+ --exclude="/projects/misc/busybox" \
+ --exclude="/projects/misc/cgit" \
+ --exclude="/projects/misc/dash" \
+ --exclude="/projects/misc/endlessh" \
+ --exclude="/projects/misc/jssc" \
+ --exclude="/projects/misc/libqrencode" \
+ --exclude="/projects/misc/mbedtls" \
+ --exclude="/projects/misc/openbox" \
+ --exclude="cee-misc-lib/external" \
+ --exclude="cee-misc-lib/tmp" \
+ --exclude="/tmp" \
+ --exclude="/virtualbox-*" \
+ --exclude="/vmshare" \
+ "${DIR_FROM:?}" \
+ "${BACKUP_PATH:?}/${DST_PREFIX}" \
+ ;
+ (cd "${DIR_TO:?}" &&
+ rm -f latest &&
+ ln --symbolic "${NOW_SHORT:?}" latest
+ )
+}
+
+
+main () {
+ parseArgs "$@"
+ if [ $? -ne 0 ]; then exit 2; fi
+ run
+}
+
+
+main "$@"