diff options
author | Tobias Schmidt <tobidt@gmail.com> | 2018-03-06 13:51:23 +0100 |
---|---|---|
committer | Tobias Schmidt <tobidt@gmail.com> | 2018-03-10 15:19:44 +0100 |
commit | 7a1a512c8ac1e71977bc9fbd13d980639147b428 (patch) | |
tree | 39d86a537beee0fd70976ee605ac8fe940951683 /ttar | |
parent | 002c1ca02917406cbecc457162e2bdb1f29c2f49 (diff) | |
download | prometheus_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-x | ttar | 133 |
1 files changed, 128 insertions, 5 deletions
@@ -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 | |||
9 | set -o errexit -o nounset | 24 | set -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 | ||
14 | path="" | 29 | path="" |
15 | CMD="" | 30 | CMD="" |
16 | ARG_STRING="$@" | 31 | ARG_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 | |||
37 | USE_PYTHON=0 | ||
38 | |||
39 | PYTHON_CREATE_FILTER=$(cat << 'PCF' | ||
40 | #!/usr/bin/env python | ||
41 | |||
42 | import re | ||
43 | import sys | ||
44 | |||
45 | for 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) | ||
50 | PCF | ||
51 | ) | ||
52 | |||
53 | PYTHON_EXTRACT_FILTER=$(cat << 'PEF' | ||
54 | #!/usr/bin/env python | ||
55 | |||
56 | import re | ||
57 | import sys | ||
58 | |||
59 | for 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) | ||
65 | PEF | ||
66 | ) | ||
67 | |||
68 | function 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 | ||
18 | function usage { | 81 | function 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 | ||
25 | Options: | 88 | Options: |
26 | -C <DIR> (change directory) | 89 | -C <DIR> (change directory) |
90 | -v (verbose) | ||
27 | 91 | ||
28 | Example: Change to sysfs directory, create ttar file from fixtures directory | 92 | Example: 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 | ||
113 | unset VERBOSE | ||
114 | |||
49 | while getopts :cf:htxvC: opt; do | 115 | while 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 { | |||
201 | function _create { | 299 | function _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 | ||
378 | test_environment | ||
379 | |||
257 | if [ -n "${CDIR:-}" ]; then | 380 | if [ -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 |