aboutsummaryrefslogtreecommitdiff
path: root/ttar
diff options
context:
space:
mode:
authorTobias Schmidt <tobidt@gmail.com>2018-03-06 13:51:23 +0100
committerTobias Schmidt <tobidt@gmail.com>2018-03-10 15:19:44 +0100
commit7a1a512c8ac1e71977bc9fbd13d980639147b428 (patch)
tree39d86a537beee0fd70976ee605ac8fe940951683 /ttar
parent002c1ca02917406cbecc457162e2bdb1f29c2f49 (diff)
downloadprometheus_node_collector-7a1a512c8ac1e71977bc9fbd13d980639147b428.tar.bz2
prometheus_node_collector-7a1a512c8ac1e71977bc9fbd13d980639147b428.tar.xz
prometheus_node_collector-7a1a512c8ac1e71977bc9fbd13d980639147b428.zip
Vendor ttar from github.com/ideaship/ttar
Diffstat (limited to 'ttar')
-rwxr-xr-xttar133
1 files changed, 128 insertions, 5 deletions
diff --git a/ttar b/ttar
index c3472c1..b0171a1 100755
--- a/ttar
+++ b/ttar
@@ -1,11 +1,26 @@
1#!/usr/bin/env bash 1#!/usr/bin/env bash
2
2# Purpose: plain text tar format 3# Purpose: plain text tar format
3# Limitations: - only suitable for text files, directories, and symlinks 4# Limitations: - only suitable for text files, directories, and symlinks
4# - stores only filename, content, and mode 5# - stores only filename, content, and mode
5# - not designed for untrusted input 6# - not designed for untrusted input
6 7#
7# Note: must work with bash version 3.2 (macOS) 8# Note: must work with bash version 3.2 (macOS)
8 9
10# Copyright 2017 Roger Luethi
11#
12# Licensed under the Apache License, Version 2.0 (the "License");
13# you may not use this file except in compliance with the License.
14# You may obtain a copy of the License at
15#
16# http://www.apache.org/licenses/LICENSE-2.0
17#
18# Unless required by applicable law or agreed to in writing, software
19# distributed under the License is distributed on an "AS IS" BASIS,
20# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21# See the License for the specific language governing permissions and
22# limitations under the License.
23
9set -o errexit -o nounset 24set -o errexit -o nounset
10 25
11# Sanitize environment (for instance, standard sorting of glob matches) 26# Sanitize environment (for instance, standard sorting of glob matches)
@@ -13,7 +28,55 @@ export LC_ALL=C
13 28
14path="" 29path=""
15CMD="" 30CMD=""
16ARG_STRING="$@" 31ARG_STRING="$*"
32
33#------------------------------------------------------------------------------
34# Not all sed implementations can work on null bytes. In order to make ttar
35# work out of the box on macOS, use Python as a stream editor.
36
37USE_PYTHON=0
38
39PYTHON_CREATE_FILTER=$(cat << 'PCF'
40#!/usr/bin/env python
41
42import re
43import sys
44
45for line in sys.stdin:
46 line = re.sub(r'EOF', r'\EOF', line)
47 line = re.sub(r'NULLBYTE', r'\NULLBYTE', line)
48 line = re.sub('\x00', r'NULLBYTE', line)
49 sys.stdout.write(line)
50PCF
51)
52
53PYTHON_EXTRACT_FILTER=$(cat << 'PEF'
54#!/usr/bin/env python
55
56import re
57import sys
58
59for line in sys.stdin:
60 line = re.sub(r'(?<!\\)NULLBYTE', '\x00', line)
61 line = re.sub(r'\\NULLBYTE', 'NULLBYTE', line)
62 line = re.sub(r'([^\\])EOF', r'\1', line)
63 line = re.sub(r'\\EOF', 'EOF', line)
64 sys.stdout.write(line)
65PEF
66)
67
68function test_environment {
69 if [[ "$(echo "a" | sed 's/a/\x0/' | wc -c)" -ne 2 ]]; then
70 echo "WARNING sed unable to handle null bytes, using Python (slow)."
71 if ! which python >/dev/null; then
72 echo "ERROR Python not found. Aborting."
73 exit 2
74 fi
75 USE_PYTHON=1
76 fi
77}
78
79#------------------------------------------------------------------------------
17 80
18function usage { 81function usage {
19 bname=$(basename "$0") 82 bname=$(basename "$0")
@@ -24,6 +87,7 @@ Usage: $bname [-C <DIR>] -c -f <ARCHIVE> <FILE...> (create archive)
24 87
25Options: 88Options:
26 -C <DIR> (change directory) 89 -C <DIR> (change directory)
90 -v (verbose)
27 91
28Example: Change to sysfs directory, create ttar file from fixtures directory 92Example: Change to sysfs directory, create ttar file from fixtures directory
29 $bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/ 93 $bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/
@@ -46,6 +110,8 @@ function set_cmd {
46 CMD=$1 110 CMD=$1
47} 111}
48 112
113unset VERBOSE
114
49while getopts :cf:htxvC: opt; do 115while getopts :cf:htxvC: opt; do
50 case $opt in 116 case $opt in
51 c) 117 c)
@@ -143,8 +209,37 @@ function extract {
143 fi 209 fi
144 while IFS= read -r line; do 210 while IFS= read -r line; do
145 line_no=$(( line_no + 1 )) 211 line_no=$(( line_no + 1 ))
212 local eof_without_newline
146 if [ "$size" -gt 0 ]; then 213 if [ "$size" -gt 0 ]; then
147 echo "$line" >> "$path" 214 if [[ "$line" =~ [^\\]EOF ]]; then
215 # An EOF not preceeded by a backslash indicates that the line
216 # does not end with a newline
217 eof_without_newline=1
218 else
219 eof_without_newline=0
220 fi
221 # Replace NULLBYTE with null byte if at beginning of line
222 # Replace NULLBYTE with null byte unless preceeded by backslash
223 # Remove one backslash in front of NULLBYTE (if any)
224 # Remove EOF unless preceeded by backslash
225 # Remove one backslash in front of EOF
226 if [ $USE_PYTHON -eq 1 ]; then
227 echo -n "$line" | python -c "$PYTHON_EXTRACT_FILTER" >> "$path"
228 else
229 # The repeated pattern makes up for sed's lack of negative
230 # lookbehind assertions (for consecutive null bytes).
231 echo -n "$line" | \
232 sed -e 's/^NULLBYTE/\x0/g;
233 s/\([^\\]\)NULLBYTE/\1\x0/g;
234 s/\([^\\]\)NULLBYTE/\1\x0/g;
235 s/\\NULLBYTE/NULLBYTE/g;
236 s/\([^\\]\)EOF/\1/g;
237 s/\\EOF/EOF/g;
238 ' >> "$path"
239 fi
240 if [[ "$eof_without_newline" -eq 0 ]]; then
241 echo >> "$path"
242 fi
148 size=$(( size - 1 )) 243 size=$(( size - 1 ))
149 continue 244 continue
150 fi 245 fi
@@ -188,11 +283,14 @@ function get_mode {
188 local mfile=$1 283 local mfile=$1
189 if [ -z "${STAT_OPTION:-}" ]; then 284 if [ -z "${STAT_OPTION:-}" ]; then
190 if stat -c '%a' "$mfile" >/dev/null 2>&1; then 285 if stat -c '%a' "$mfile" >/dev/null 2>&1; then
286 # GNU stat
191 STAT_OPTION='-c' 287 STAT_OPTION='-c'
192 STAT_FORMAT='%a' 288 STAT_FORMAT='%a'
193 else 289 else
290 # BSD stat
194 STAT_OPTION='-f' 291 STAT_OPTION='-f'
195 STAT_FORMAT='%A' 292 # Octal output, user/group/other (omit file type, sticky bit)
293 STAT_FORMAT='%OLp'
196 fi 294 fi
197 fi 295 fi
198 stat "${STAT_OPTION}" "${STAT_FORMAT}" "$mfile" 296 stat "${STAT_OPTION}" "${STAT_FORMAT}" "$mfile"
@@ -201,6 +299,7 @@ function get_mode {
201function _create { 299function _create {
202 shopt -s nullglob 300 shopt -s nullglob
203 local mode 301 local mode
302 local eof_without_newline
204 while (( "$#" )); do 303 while (( "$#" )); do
205 file=$1 304 file=$1
206 if [ -L "$file" ]; then 305 if [ -L "$file" ]; then
@@ -224,8 +323,30 @@ function _create {
224 elif [ -f "$file" ]; then 323 elif [ -f "$file" ]; then
225 echo "Path: $file" 324 echo "Path: $file"
226 lines=$(wc -l "$file"|awk '{print $1}') 325 lines=$(wc -l "$file"|awk '{print $1}')
326 eof_without_newline=0
327 if [[ "$(wc -c "$file"|awk '{print $1}')" -gt 0 ]] && \
328 [[ "$(tail -c 1 "$file" | wc -l)" -eq 0 ]]; then
329 eof_without_newline=1
330 lines=$((lines+1))
331 fi
227 echo "Lines: $lines" 332 echo "Lines: $lines"
228 cat "$file" 333 # Add backslash in front of EOF
334 # Add backslash in front of NULLBYTE
335 # Replace null byte with NULLBYTE
336 if [ $USE_PYTHON -eq 1 ]; then
337 < "$file" python -c "$PYTHON_CREATE_FILTER"
338 else
339 < "$file" \
340 sed 's/EOF/\\EOF/g;
341 s/NULLBYTE/\\NULLBYTE/g;
342 s/\x0/NULLBYTE/g;
343 '
344 fi
345 if [[ "$eof_without_newline" -eq 1 ]]; then
346 # Finish line with EOF to indicate that the original line did
347 # not end with a linefeed
348 echo "EOF"
349 fi
229 mode=$(get_mode "$file") 350 mode=$(get_mode "$file")
230 echo "Mode: $mode" 351 echo "Mode: $mode"
231 vecho "$mode $file" 352 vecho "$mode $file"
@@ -254,6 +375,8 @@ function create {
254 _create "$@" 375 _create "$@"
255} 376}
256 377
378test_environment
379
257if [ -n "${CDIR:-}" ]; then 380if [ -n "${CDIR:-}" ]; then
258 if [[ "$ARCHIVE" != /* ]]; then 381 if [[ "$ARCHIVE" != /* ]]; then
259 # Relative path: preserve the archive's location before changing 382 # Relative path: preserve the archive's location before changing