prometheusmetricshost-metricsmachine-metricsnode-metricsprocfsprometheus-exportersystem-informationsystem-metrics
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
6.5 KiB
266 lines
6.5 KiB
#!/usr/bin/env bash |
|
# Purpose: plain text tar format |
|
# Limitations: - only suitable for text files, directories, and symlinks |
|
# - stores only filename, content, and mode |
|
# - not designed for untrusted input |
|
|
|
# Note: must work with bash version 3.2 (macOS) |
|
|
|
set -o errexit -o nounset |
|
|
|
# Sanitize environment (for instance, standard sorting of glob matches) |
|
export LC_ALL=C |
|
|
|
path="" |
|
CMD="" |
|
ARG_STRING="$@" |
|
|
|
function usage { |
|
bname=$(basename "$0") |
|
cat << USAGE |
|
Usage: $bname [-C <DIR>] -c -f <ARCHIVE> <FILE...> (create archive) |
|
$bname -t -f <ARCHIVE> (list archive contents) |
|
$bname [-C <DIR>] -x -f <ARCHIVE> (extract archive) |
|
|
|
Options: |
|
-C <DIR> (change directory) |
|
|
|
Example: Change to sysfs directory, create ttar file from fixtures directory |
|
$bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/ |
|
USAGE |
|
exit "$1" |
|
} |
|
|
|
function vecho { |
|
if [ "${VERBOSE:-}" == "yes" ]; then |
|
echo >&7 "$@" |
|
fi |
|
} |
|
|
|
function set_cmd { |
|
if [ -n "$CMD" ]; then |
|
echo "ERROR: more than one command given" |
|
echo |
|
usage 2 |
|
fi |
|
CMD=$1 |
|
} |
|
|
|
while getopts :cf:htxvC: opt; do |
|
case $opt in |
|
c) |
|
set_cmd "create" |
|
;; |
|
f) |
|
ARCHIVE=$OPTARG |
|
;; |
|
h) |
|
usage 0 |
|
;; |
|
t) |
|
set_cmd "list" |
|
;; |
|
x) |
|
set_cmd "extract" |
|
;; |
|
v) |
|
VERBOSE=yes |
|
exec 7>&1 |
|
;; |
|
C) |
|
CDIR=$OPTARG |
|
;; |
|
*) |
|
echo >&2 "ERROR: invalid option -$OPTARG" |
|
echo |
|
usage 1 |
|
;; |
|
esac |
|
done |
|
|
|
# Remove processed options from arguments |
|
shift $(( OPTIND - 1 )); |
|
|
|
if [ "${CMD:-}" == "" ]; then |
|
echo >&2 "ERROR: no command given" |
|
echo |
|
usage 1 |
|
elif [ "${ARCHIVE:-}" == "" ]; then |
|
echo >&2 "ERROR: no archive name given" |
|
echo |
|
usage 1 |
|
fi |
|
|
|
function list { |
|
local path="" |
|
local size=0 |
|
local line_no=0 |
|
local ttar_file=$1 |
|
if [ -n "${2:-}" ]; then |
|
echo >&2 "ERROR: too many arguments." |
|
echo |
|
usage 1 |
|
fi |
|
if [ ! -e "$ttar_file" ]; then |
|
echo >&2 "ERROR: file not found ($ttar_file)" |
|
echo |
|
usage 1 |
|
fi |
|
while read -r line; do |
|
line_no=$(( line_no + 1 )) |
|
if [ $size -gt 0 ]; then |
|
size=$(( size - 1 )) |
|
continue |
|
fi |
|
if [[ $line =~ ^Path:\ (.*)$ ]]; then |
|
path=${BASH_REMATCH[1]} |
|
elif [[ $line =~ ^Lines:\ (.*)$ ]]; then |
|
size=${BASH_REMATCH[1]} |
|
echo "$path" |
|
elif [[ $line =~ ^Directory:\ (.*)$ ]]; then |
|
path=${BASH_REMATCH[1]} |
|
echo "$path/" |
|
elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then |
|
echo "$path -> ${BASH_REMATCH[1]}" |
|
fi |
|
done < "$ttar_file" |
|
} |
|
|
|
function extract { |
|
local path="" |
|
local size=0 |
|
local line_no=0 |
|
local ttar_file=$1 |
|
if [ -n "${2:-}" ]; then |
|
echo >&2 "ERROR: too many arguments." |
|
echo |
|
usage 1 |
|
fi |
|
if [ ! -e "$ttar_file" ]; then |
|
echo >&2 "ERROR: file not found ($ttar_file)" |
|
echo |
|
usage 1 |
|
fi |
|
while IFS= read -r line; do |
|
line_no=$(( line_no + 1 )) |
|
if [ "$size" -gt 0 ]; then |
|
echo "$line" >> "$path" |
|
size=$(( size - 1 )) |
|
continue |
|
fi |
|
if [[ $line =~ ^Path:\ (.*)$ ]]; then |
|
path=${BASH_REMATCH[1]} |
|
if [ -e "$path" ] || [ -L "$path" ]; then |
|
rm "$path" |
|
fi |
|
elif [[ $line =~ ^Lines:\ (.*)$ ]]; then |
|
size=${BASH_REMATCH[1]} |
|
# Create file even if it is zero-length. |
|
touch "$path" |
|
vecho " $path" |
|
elif [[ $line =~ ^Mode:\ (.*)$ ]]; then |
|
mode=${BASH_REMATCH[1]} |
|
chmod "$mode" "$path" |
|
vecho "$mode" |
|
elif [[ $line =~ ^Directory:\ (.*)$ ]]; then |
|
path=${BASH_REMATCH[1]} |
|
mkdir -p "$path" |
|
vecho " $path/" |
|
elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then |
|
ln -s "${BASH_REMATCH[1]}" "$path" |
|
vecho " $path -> ${BASH_REMATCH[1]}" |
|
elif [[ $line =~ ^# ]]; then |
|
# Ignore comments between files |
|
continue |
|
else |
|
echo >&2 "ERROR: Unknown keyword on line $line_no: $line" |
|
exit 1 |
|
fi |
|
done < "$ttar_file" |
|
} |
|
|
|
function div { |
|
echo "# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" \ |
|
"- - - - - -" |
|
} |
|
|
|
function get_mode { |
|
local mfile=$1 |
|
if [ -z "${STAT_OPTION:-}" ]; then |
|
if stat -c '%a' "$mfile" >/dev/null 2>&1; then |
|
STAT_OPTION='-c' |
|
STAT_FORMAT='%a' |
|
else |
|
STAT_OPTION='-f' |
|
STAT_FORMAT='%A' |
|
fi |
|
fi |
|
stat "${STAT_OPTION}" "${STAT_FORMAT}" "$mfile" |
|
} |
|
|
|
function _create { |
|
shopt -s nullglob |
|
local mode |
|
while (( "$#" )); do |
|
file=$1 |
|
if [ -L "$file" ]; then |
|
echo "Path: $file" |
|
symlinkTo=$(readlink "$file") |
|
echo "SymlinkTo: $symlinkTo" |
|
vecho " $file -> $symlinkTo" |
|
div |
|
elif [ -d "$file" ]; then |
|
# Strip trailing slash (if there is one) |
|
file=${file%/} |
|
echo "Directory: $file" |
|
mode=$(get_mode "$file") |
|
echo "Mode: $mode" |
|
vecho "$mode $file/" |
|
div |
|
# Find all files and dirs, including hidden/dot files |
|
for x in "$file/"{*,.[^.]*}; do |
|
_create "$x" |
|
done |
|
elif [ -f "$file" ]; then |
|
echo "Path: $file" |
|
lines=$(wc -l "$file"|awk '{print $1}') |
|
echo "Lines: $lines" |
|
cat "$file" |
|
mode=$(get_mode "$file") |
|
echo "Mode: $mode" |
|
vecho "$mode $file" |
|
div |
|
else |
|
echo >&2 "ERROR: file not found ($file in $(pwd))" |
|
exit 2 |
|
fi |
|
shift |
|
done |
|
} |
|
|
|
function create { |
|
ttar_file=$1 |
|
shift |
|
if [ -z "${1:-}" ]; then |
|
echo >&2 "ERROR: missing arguments." |
|
echo |
|
usage 1 |
|
fi |
|
if [ -e "$ttar_file" ]; then |
|
rm "$ttar_file" |
|
fi |
|
exec > "$ttar_file" |
|
echo "# Archive created by ttar $ARG_STRING" |
|
_create "$@" |
|
} |
|
|
|
if [ -n "${CDIR:-}" ]; then |
|
if [[ "$ARCHIVE" != /* ]]; then |
|
# Relative path: preserve the archive's location before changing |
|
# directory |
|
ARCHIVE="$(pwd)/$ARCHIVE" |
|
fi |
|
cd "$CDIR" |
|
fi |
|
|
|
"$CMD" "$ARCHIVE" "$@"
|
|
|