-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathvalidate-core-package.sh
More file actions
executable file
·149 lines (132 loc) · 5.03 KB
/
Copy pathvalidate-core-package.sh
File metadata and controls
executable file
·149 lines (132 loc) · 5.03 KB
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
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 1 ]]; then
printf 'usage: %s <vitasdk-core-*.pkg.tar.*>\n' "$0" >&2
exit 2
fi
package=$1
require_package_client=${REQUIRE_PACKAGE_CLIENT:-1}
[[ -f $package ]] || {
printf 'core package not found: %s\n' "$package" >&2
exit 1
}
package_filename=${package##*/}
pkginfo=$(bsdtar -xOf "$package" .PKGINFO) || {
printf 'cannot read .PKGINFO from %s\n' "$package_filename" >&2
exit 1
}
pkgname=$(awk -F ' = ' '$1 == "pkgname" { print $2; exit }' <<< "$pkginfo")
pkgver=$(awk -F ' = ' '$1 == "pkgver" { print $2; exit }' <<< "$pkginfo")
architecture=$(awk -F ' = ' '$1 == "arch" { print $2; exit }' <<< "$pkginfo")
# A core release ships the toolchain and the client that installs it, as two
# packages, so both names are valid here and each has to own its own file name.
[[ ($pkgname == vitasdk-core || $pkgname == vdpm) && -n $pkgver && -n $architecture ]] || {
printf 'invalid core package identity\n' >&2
exit 1
}
[[ $package_filename == "$pkgname-$pkgver-$architecture.pkg.tar."* ]] || {
printf 'core package filename does not match its metadata: %s\n' \
"$package_filename" >&2
exit 1
}
archive_entries=$(bsdtar -tf "$package")
for metadata in .PKGINFO .BUILDINFO .MTREE; do
grep -qx "$metadata" <<< "$archive_entries" || {
printf '%s is missing from %s\n' "$metadata" "$package_filename" >&2
exit 1
}
done
if grep -E '(^/|(^|/)\.\.(/|$))' <<< "$archive_entries"; then
printf 'core package contains an unsafe path\n' >&2
exit 1
fi
bsdtar -xOf "$package" .MTREE | gzip -t
if [[ $pkgname == vitasdk-core ]]; then
grep -Eq '^bin/arm-vita-eabi-gcc(\.exe)?$' <<< "$archive_entries" || {
printf 'core package does not contain the Vita compiler driver\n' >&2
exit 1
}
grep -qx 'version_info.txt' <<< "$archive_entries" || {
printf 'core package does not contain provenance information\n' >&2
exit 1
}
# The world (vita, vita-softfp, ...) is stamped in two independent places;
# a mismatch means the build tagged the release for one world while
# actually configuring the toolchain, or makepkg, for another.
world_from_version=$(bsdtar -xOf "$package" version_info.txt |
awk '$1 == "world" { print $2; exit }')
[[ -n $world_from_version ]] || {
printf 'version_info.txt does not declare a world\n' >&2
exit 1
}
grep -qx 'bin/makepkg.conf' <<< "$archive_entries" || {
printf 'core package does not contain bin/makepkg.conf\n' >&2
exit 1
}
world_from_makepkg=$(bsdtar -xOf "$package" bin/makepkg.conf |
awk -F '"' '/^CARCH=/ { print $2; exit }')
[[ -n $world_from_makepkg ]] || {
printf 'bin/makepkg.conf does not declare CARCH\n' >&2
exit 1
}
[[ $world_from_version == "$world_from_makepkg" ]] || {
printf 'world mismatch: version_info.txt says %s, bin/makepkg.conf CARCH says %s\n' \
"$world_from_version" "$world_from_makepkg" >&2
exit 1
}
else
grep -Eq '^bin/vdpm(\.exe)?$' <<< "$archive_entries" || {
printf 'client package does not contain the package client\n' >&2
exit 1
}
fi
# Nothing owns etc/pacman.conf: refresh writes it to name the selected
# channel, and a package owning it would put the selection back.
grep -qx 'etc/pacman.conf' <<< "$archive_entries" && {
printf '%s owns etc/pacman.conf\n' "$pkgname" >&2
exit 1
}
# An msys-2.0.dll under the SDK's own usr/bin makes the SDK an MSYS root, and
# an MSYS root turns /bin into an alias of /usr/bin: pacman would then write
# every bin/ file a package installs -- the whole toolchain front end -- into
# usr/bin instead. The runtime lives in a root of its own under share/vdpm, so
# nothing here may put anything in usr/. Repacking an older tree is how one
# would arrive back at it.
if [[ $architecture == *-w64-mingw32 ]] && grep -q '^usr/' <<< "$archive_entries"; then
printf '%s installs into the SDK own usr/, which makes it an MSYS root\n' \
"$pkgname" >&2
exit 1
fi
if [[ $pkgname == vdpm ]]; then
for compliance_file in share/vdpm/THIRD_PARTY_NOTICES.md \
share/vdpm/licenses/vdpm-LGPL-2.1.txt \
share/vdpm/licenses/pacman-GPL-2.0.txt; do
grep -Fqx "$compliance_file" <<< "$archive_entries" || {
printf 'client package does not contain %s\n' "$compliance_file" >&2
exit 1
}
done
if [[ $architecture == *-w64-mingw32 ]]; then
for runtime_file in bin/vdpm.exe \
share/vdpm/msys/usr/bin/pacman.exe \
share/vdpm/msys/usr/bin/vdpm-channel.exe \
share/vdpm/msys/usr/bin/msys-2.0.dll \
share/vdpm/refresh-repositories.ps1; do
grep -Fqx "$runtime_file" <<< "$archive_entries" || {
printf 'Windows client package does not contain %s\n' "$runtime_file" >&2
exit 1
}
done
else
for runtime_file in bin/vdpm libexec/vdpm/pacman bin/vdpm-channel; do
grep -Fqx "$runtime_file" <<< "$archive_entries" || {
printf 'client package does not contain %s\n' "$runtime_file" >&2
exit 1
}
done
fi
fi
# The contract that pacman.conf selects both architectures, declares the
# external trust model and embeds no repository URL now belongs to whoever
# writes it, which is refresh, and is asserted in the client's own tests.
printf 'validated core package %s for %s\n' "$pkgver" "$architecture"