#!/usr/bin/env bash if [[ -n ${IPF_STORAGE_SH_LOADED:-} ]]; then return 0 fi IPF_STORAGE_SH_LOADED=1 : "${IPF_STORAGE_DIR:=/var/lib/iptables-forward}" : "${IPF_STORAGE_DB:=${IPF_STORAGE_DIR}/rules.db}" : "${IPF_LOCK_FILE:=${IPF_STORAGE_DIR}/.lock}" storage_dir() { printf '%s\n' "${IPF_STORAGE_DIR}" } storage_db_path() { printf '%s\n' "${IPF_STORAGE_DB}" } storage_lock_path() { printf '%s\n' "${IPF_LOCK_FILE}" } storage_init() { local dir db lock dir=$(storage_dir) db=$(storage_db_path) lock=$(storage_lock_path) mkdir -p "${dir}" touch "${db}" "${lock}" chmod 750 "${dir}" chmod 640 "${db}" chmod 600 "${lock}" } storage_add() { local line=${1-} local db lock [[ -n ${line} ]] || return 1 storage_init db=$(storage_db_path) lock=$(storage_lock_path) ( flock -x 9 printf '%s\n' "${line}" >>"${db}" ) 9>>"${lock}" } storage_list() { local db db=$(storage_db_path) [[ -f ${db} ]] || return 0 cat "${db}" } storage_parse() { local line=${1-} local key=${2-} local part IFS='|' read -r -a parts <<<"${line}" for part in "${parts[@]}"; do if [[ ${part} == "${key}="* ]]; then printf '%s\n' "${part#*=}" return 0 fi done return 1 } storage_get() { local uuid=${1-} local line current [[ -n ${uuid} ]] || return 1 while IFS= read -r line || [[ -n ${line} ]]; do current=$(storage_parse "${line}" uuid || true) if [[ ${current} == "${uuid}" ]]; then printf '%s\n' "${line}" return 0 fi done < <(storage_list) return 1 } storage_delete() { local uuid=${1-} local db lock tmp found=0 line current [[ -n ${uuid} ]] || return 1 storage_init db=$(storage_db_path) lock=$(storage_lock_path) tmp="${db}.tmp.$$" ( flock -x 9 : >"${tmp}" while IFS= read -r line || [[ -n ${line} ]]; do current=$(storage_parse "${line}" uuid || true) if [[ ${current} == "${uuid}" ]]; then found=1 continue fi printf '%s\n' "${line}" >>"${tmp}" done <"${db}" if (( found == 0 )); then rm -f "${tmp}" exit 1 fi mv "${tmp}" "${db}" ) 9>>"${lock}" } storage_count() { local count=0 line while IFS= read -r line || [[ -n ${line} ]]; do [[ -n ${line} ]] || continue ((count++)) done < <(storage_list) printf '%s\n' "${count}" }