#!/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 mb_manifest=MANIFEST.rawball 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 ' >&2 printf '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() { export LC_ALL='C' 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) > ${mb_manifest}) touch -a -c -m -r ${mb_refobj} $(find ${mb_rawdir} -type d) touch -a -c -m -r ${mb_refobj} ${mb_rawdir}/${mb_manifest} touch -a -c -m -r ${mb_refobj} ${mb_rawdir} } rawball_create_downstream_rawball() { pax -w -x tar ${mb_packed} ${mb_rawdir}/${mb_manifest} | 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