-
Notifications
You must be signed in to change notification settings - Fork 1
/
blob2oci
executable file
·168 lines (119 loc) · 4.71 KB
/
blob2oci
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#!/bin/bash
# blob2oci - Simple shell tool to pull from DockerHub and create an OCI image.
# Copyright (C) 2018 Oliver Freyermuth
#
# Contributors
# - Vanessa Sochat
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
# Functions
function handle_whiteouts() {
# Layer and extract folder required
if [ "$#" -ne 2 ]; then
printHelp;
exit 1;
fi
layer="${1}"
extract="${2}"
# Checks
if [ ! -f "${layer}" ]; then
echo "Cannot find ${layer}"
exit 1
fi
if [ ! -d "${extract}" ]; then
echo "Cannot find directory ${extract} to extract."
exit 1
fi
# Whiteout handling.
whiteouts_unchecked=$(tar tf ${layer} --wildcards --wildcards-match-slash ".wh..wh..opq" "*/.wh..wh..opq" ".wh.*" "*/.wh.*" 2>/dev/null)
# Checking for whiteouts with newline
num_bad_whiteouts=$(echo -n "${whiteouts_unchecked}" | grep -v '.wh.' | wc -l)
if [ ! ${num_bad_whiteouts} -eq 0 ]; then
echo "There are ${num_bad_whiteouts} whiteout files with newline characters in the filename in layer ${layer}:"
echo "${whiteouts_unchecked}" | grep -v '.wh.'
echo "This is likely malicious content, exiting now!"
exit 1
fi
whiteouts=$(echo "${whiteouts_unchecked}" | tr '\n' '\0' | xxd -p)
# Opaque Whiteouts
opaque_whiteouts=$(echo -n "${whiteouts_unchecked}" | xxd -p -r | grep -ze '\.wh\.\.wh\.\.opq$' | xxd -p)
if [ ! -z "${opaque_whiteouts}" ]; then
echo "Warning: Layer ${layer} contains opaque whiteout files:"
while IFS= read -r -d '' whiteout_file; do
echo "${whiteout_file}"
done < <(echo -n "${opaque_whiteouts}" | xxd -p -r)
echo "We do not handle these yet!"
fi
# Explicit Whiteouts
explicit_whiteouts=$(echo -n "${whiteouts}" | xxd -p -r | grep -zve '\.wh\.\.wh\.\.opq$' | grep -ze '\.wh\.[^/]\+$' | xxd -p)
if [ ! -z "${explicit_whiteouts}" ]; then
while IFS= read -r -d '' whiteout_file; do
to_be_deleted=${extract}/$(echo "${whiteout_file}" | sed 's#\.wh\.\([^/]\+\)$#\1#')
# If the directory was already deleted, the file won't exist
if [ -e "$to_be_deleted" ]; then
# Where is the file linking to?
location=$(readlink -f "${to_be_deleted}")
echo "file:$to_be_deleted --> location:$location";
# If the link isn't within the extraction tree, remove
if [[ ${location} == ${extract}* ]]; then
rm -rf "${to_be_deleted}";
# Otherwise, could have malicious intent
else
echo "WARNING: File ${to_be_deleted} links outside of tree. Will not be deleted.";
fi
fi
done < <(echo -n "${explicit_whiteouts}" | xxd -p -r)
fi
tar --overwrite --exclude=dev/* --exclude=*/.wh.* -C ${extract} -xf ${layer}
}
################################################################################
# Main
function run_handle_whiteouts() {
function printHelp() {
cat <<EOF
Tool to extract a layer to a folder of interest, handling whiteout files.
Example usage:
$0 --layer /path/to/file.tar.gz --extract /extract/here
EOF
exit 1
}
writable_dirs=false
# Argument Parsing
TEMP=$(getopt -o h --long layer:,extract:,writable-dirs,help -n $0 -- "$@")
if [ $? != 0 ] ; then printHelp; exit 1; fi
eval set -- "$TEMP"
while true ; do
case "$1" in
--layer) layer=$2; shift 2;;
--extract) extract=$2; shift 2;;
--writable-dirs) writable_dirs=true; shift 1;;
-h|--help) printHelp; exit 0;;
--) shift; break;;
*) echo "Internal error!"; exit 1;;
esac
done
# Main
handle_whiteouts "${layer}" "${extract}"
# Make directories owner-writable?
if ${writable_dirs}; then
find ${extract} -type d ! -perm -200 -print0|xargs -0 -r chmod u+w
fi
}
# If the script has arguments, not being sourced
if [ "$#" -ne 0 ]; then
run_handle_whiteouts "$@"
else
exec $0 --help
fi