summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xbin/srcdist.rawball165
1 files changed, 165 insertions, 0 deletions
diff --git a/bin/srcdist.rawball b/bin/srcdist.rawball
new file mode 100755
index 0000000..5df09ea
--- /dev/null
+++ b/bin/srcdist.rawball
@@ -0,0 +1,165 @@
+#!/bin/sh
+
+# srcdist.rawball: extract and repackage a subset of unmodified source files
+# from a known upstream source distribution tarball, along with a manifest.
+
+# this file is covered by COPYING.SRCDIST.
+
+set -eu
+
+mb_ruledir=
+mb_rawball=
+mb_tarball=
+mb_tarball_sha256=
+
+mb_script="$0"
+mb_status=1
+
+export LC_ALL=C
+
+rawball_usage()
+{
+ printf 'usage: %s\n' "$mb_script" >&2
+ printf '\t%s\n' \
+ '--ruledir=/path/to/rule/dir' \
+ '--tarball=/path/to/upstream.tar.xz' \
+ '--tarball-sha256=upstream-signature' \
+ '--rawball=output-tarball-name' \
+ >&2
+
+ printf '\nThis will extract and repackage a subset of unmodified source\n' >&2
+ printf ' files from a known upstream source distribution tarball,\n' >&2
+ printf ' along with a manifest.\n\n' >&2
+
+ printf '\nThe --ruledir argument should point to a directory containing the following files:\n' >&2
+ printf ' upstream.sha256.known\n' >&2
+ printf ' rawball.include.patterns (appropriate for pax)\n' >&2
+ printf ' rawball.exclude.patterns (appropriate for grep -v -f)\n\n' >&2
+
+ exit ${mb_status}
+}
+
+for arg ; do
+ case "$arg" in
+ --ruledir=*)
+ mb_ruledir=${arg#*=}
+ ;;
+
+ --rawball=*)
+ mb_rawball=${arg#*=}
+ ;;
+
+ --tarball=*)
+ mb_tarball=${arg#*=}
+ ;;
+
+ --tarball-sha256=*)
+ mb_tarball_sha256=${arg#*=}
+ ;;
+
+ *)
+ printf '\n*** %s: unsupported argument!' "$mb_script" >&2
+ printf '\n*** %s\n' "${arg#}" >&2
+ exit 2
+ esac
+done
+
+rawball_ruledir_error()
+{
+ mb_status=2
+
+ printf '\n*** %s: a required file in %s is missing!\n\n' "$mb_script" "$mb_ruledir" >&2
+
+ rawball_usage
+}
+
+rawball_init_vars()
+{
+ if [ -z ${mb_ruledir:-} ]; then
+ rawball_usage
+ fi
+
+
+ if [ -z ${mb_rawball:-} ] || [ -z ${mb_tarball:-} ] || [ -z ${mb_tarball_sha256:-} ]; then
+ rawball_usage
+ fi
+
+
+ eval mb_ruledir=$(printf '%s' "$mb_ruledir")
+ eval mb_tarball=$(printf '%s' "$mb_tarball")
+
+
+ stat "$mb_ruledir/upstream.sha256.known" > /dev/null || rawball_ruledir_error
+ stat "$mb_ruledir/rawball.include.patterns" > /dev/null || rawball_ruledir_error
+ stat "$mb_ruledir/rawball.exclude.patterns" > /dev/null || rawball_ruledir_error
+
+
+ mb_known_sha256=$(grep "$mb_tarball_sha256" "${mb_ruledir}/upstream.sha256.known" || true)
+ mb_known_sha256="${mb_known_sha256%% *}"
+
+ if [ "$mb_known_sha256" != "$mb_tarball_sha256" ]; then
+ printf '\n*** %s: %s is not a known sha-256 signature!\n\n' "$mb_script" "$mb_tarball_sha256" >&2
+ exit 2
+ fi
+}
+
+rawball_verify_sha256_signature()
+{
+ mb_tarball_sha256_test=$(sha256sum "$mb_tarball")
+ mb_tarball_sha256_test="${mb_tarball_sha256_test%% *}"
+
+ if [ "$mb_tarball_sha256_test" != "$mb_tarball_sha256" ]; then
+ printf '\n*** %s: sha-256 signature does not match!\n\n' "$mb_script" >&2
+ exit 2
+ fi
+
+}
+
+rawball_extract_upstream_tarball()
+{
+ mb_rawball_files=$(xz -d -c -f "$mb_tarball" \
+ | pax $(cat "$mb_ruledir/rawball.include.patterns") \
+ | grep -v -f "${mb_ruledir}/rawball.exclude.patterns" \
+ | sort)
+
+ mb_topdir=$(printf '%s\n' ${mb_rawball_files} | sed -n 1p)
+ mb_topdir=${mb_topdir%%/*}
+ mb_rawdir=${mb_topdir}.raw
+
+ if [ -d ${mb_rawdir} ]; then
+ printf '\n*** %s: the directory `%s already exists!\n\n' "$mb_script" "${mb_rawdir}'" >&2
+ exit 2
+ fi
+
+ mkdir ${mb_rawdir}
+
+ xz -d -c -f "$mb_tarball" | pax -d -r -s "/^${mb_topdir}/${mb_rawdir}/" ${mb_rawball_files}
+
+ mb_packed=$(find ${mb_rawdir} -type f | sort)
+ mb_refobj=$(find ${mb_rawdir} -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n 1)
+ mb_status=$(cd -- ${mb_rawdir}; sha256sum $(find . -type f | sort) > MANIFEST.RAWBALL)
+
+ touch -a -c -m -r ${mb_refobj} $(find ${mb_rawdir} -type d)
+ touch -a -c -m -r ${mb_refobj} ${mb_rawdir}/MANIFEST.RAWBALL
+ touch -a -c -m -r ${mb_refobj} ${mb_rawdir}
+}
+
+rawball_create_downstream_rawball()
+{
+ pax -w -x tar ${mb_packed} ${mb_rawdir}/MANIFEST.RAWBALL | xz -c > "$mb_rawball"
+}
+
+# init variables and verify arguments
+rawball_init_vars
+
+# validate input
+rawball_verify_sha256_signature
+
+# extract tarball (top-level directory must not exist)
+rawball_extract_upstream_tarball
+
+# create downstream rawball of unmodified source files
+rawball_create_downstream_rawball
+
+# all done
+exit 0