X-Git-Url: https://git.plutz.net/?p=confetti;a=blobdiff_plain;f=cgilite%2Fstorage.sh;fp=cgilite%2Fstorage.sh;h=7f70e6480d6c89c8a32d3a9ee3fb68a5bfcc35b6;hp=0000000000000000000000000000000000000000;hb=76c1e7bff1a8604ef2ef7da5d274d0db0e639139;hpb=90288ab07bb1ec83a91581fadc674a87a250a853 diff --git a/cgilite/storage.sh b/cgilite/storage.sh new file mode 100755 index 0000000..7f70e64 --- /dev/null +++ b/cgilite/storage.sh @@ -0,0 +1,129 @@ +#!/bin/sh + +# Copyright 2018, 2019 Paul Hänsch +# +# This is a file format helper, part of CGIlite. +# +# CGIlite is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# CGIlite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with CGIlite. If not, see . + +[ -n "$include_storage" ] && return 0 +include_storage="$0" + +CR=" " +BR=' +' + +LOCK(){ + local lock timeout block + lock="${1}.lock" + timeout="${2-20}" + if [ \! -w "${lock%/*}" ] || [ -e "$lock" -a \! -d "$lock" ]; then + printf 'Impossible to get lock: %s\n' "$lock" >&2 + return 1 + fi + + while ! mkdir "$lock" 2>&-; do + block="$(cat "$lock/pid" || printf 1)" + if ! { ps -eo pid |grep -qwF "$block"; }; then + printf 'Overriding stale lock: %s\n' "$lock" >&2 + break + fi + if [ $timeout -le 0 ]; then + printf 'Timeout while trying to get lock: %s\n' "$lock" >&2 + return 1 + fi + timeout=$((timeout - 1)) + sleep 1 + done + printf '%i\n' $$ >"${lock}/pid" + return 0 +} + +RELEASE(){ + local lock + lock="${1}.lock" + if [ "$(cat "$lock/pid")" = "$$" ]; then + rm "$lock/pid" + if ! rmdir "$lock"; then + printf 'Cannot remove tainted lock: %s\n' "$lock" >&2 + printf '%i\n' $$ >"${lock}/pid" + return 1 + fi + return 0 + else + printf 'Refusing to release foreign lock: %s\n' "$lock" >&2 + return 1 + fi +} + +STRING=' + s;\\;\\\\;g; + s;\n;\\n;g; + s;\t;\\t;g; + s;\r;\\r;g; + s;\+;\\+;g; + s; ;+;g; +' + +STRING_OLD(){ + { [ $# -eq 0 ] && cat || printf %s "$*"; } \ + | sed -E ':X; $!{N;bX;}'"$STRING" +} + +STRING(){ + local in out='' + [ $# -gt 0 ] && in="$*" || in="$(cat)" + while [ "$in" ]; do case $in in + \\*) out="${out}\\\\"; in="${in#\\}" ;; + "$BR"*) out="${out}\\n"; in="${in#${BR}}" ;; + "$CR"*) out="${out}\\r"; in="${in#${CR}}" ;; + " "*) out="${out}\\t"; in="${in# }" ;; + +*) out="${out}\\+"; in="${in#+}" ;; + " "*) out="${out}+"; in="${in# }" ;; + *) out="${out}${in%%[\\${CR}${BR} + ]*}"; in="${in#"${in%%[\\${BR}${CR} + ]*}"}" ;; + esac; done + printf '%s' "$out" +} + + +UNSTRING=' + :UNSTRING_X + s;((^|[^\\])(\\\\)*)\\n;\1\n;g; + s;((^|[^\\])(\\\\)*)\\t;\1\t;g; + s;((^|[^\\])(\\\\)*)\\r;\1\r;g; + s;((^|[^\\])(\\\\)*)\+;\1 ;g; + tUNSTRING_X; + s;((^|[^\\])(\\\\)*)\\\+;\1+;g; + s;\\\\;\\;g; +' +UNSTRING_OLD(){ + { [ $# -eq 0 ] && cat || printf %s "$*"; } \ + | sed -E "$UNSTRING" +} +UNSTRING(){ + local in out='' + [ $# -gt 0 ] && in="$*" || in="$(cat)" + while [ "$in" ]; do case $in in + \\\\*) out="${out}\\"; in="${in#\\\\}" ;; + \\n*) out="${out}${BR}"; in="${in#\\n}" ;; + \\r*) out="${out}${CR}"; in="${in#\\r}" ;; + \\t*) out="${out} "; in="${in#\\t}" ;; + \\+) out="${out}+"; in="${in#\\+}" ;; + +*) out="${out} "; in="${in#+}" ;; + \\*) in="${in#\\}" ;; + *) out="${out}${in%%[\\+]*}"; in="${in#"${in%%[\\+]*}"}" ;; + esac; done + printf '%s' "$out" +} +