#!/usr/bin/env bash set -Eeuo pipefail umask 022 SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" # shellcheck source=lib.sh . "${SCRIPT_DIR}/lib.sh" STAGE_DIR="" OUTPUT_DIR="${RKMEDIA_ROOT}/out" PACKAGE_VERSION="$(tr -d '[:space:]' < "${RKMEDIA_ROOT}/VERSION")" DEPENDS_FROM_DEB="" usage() { printf 'Usage: package-media.sh --stage DIRECTORY [--output-dir DIRECTORY] [--version VERSION] [--depends-from-deb FILE]\n' } while (($#)); do case "$1" in --stage) [[ $# -ge 2 ]] || die "--stage requires a directory"; STAGE_DIR="$2"; shift 2 ;; --output-dir) [[ $# -ge 2 ]] || die "--output-dir requires a directory"; OUTPUT_DIR="$2"; shift 2 ;; --version) [[ $# -ge 2 ]] || die "--version requires a value"; PACKAGE_VERSION="$2"; shift 2 ;; --depends-from-deb) [[ $# -ge 2 ]] || die "--depends-from-deb requires a file"; DEPENDS_FROM_DEB="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) die "unknown argument: $1" ;; esac done [[ -n "${STAGE_DIR}" ]] || die "--stage is required" [[ "${PACKAGE_VERSION}" =~ ^[0-9A-Za-z.+:~-]+$ ]] || die "invalid Debian package version: ${PACKAGE_VERSION}" for command_name in dpkg-deb dpkg-shlibdeps file jq md5sum sed sha256sum; do need_command "${command_name}" done STAGE_DIR="$(absolute_path "${STAGE_DIR}")" OUTPUT_DIR="$(absolute_path "${OUTPUT_DIR}")" [[ -x "${STAGE_DIR}/opt/rkmedia/bin/ffmpeg" ]] || die "stage does not contain the RKMedia runtime" mkdir -p -- "${OUTPUT_DIR}" PACKAGE_ROOT="${OUTPUT_DIR}/package-root" reset_child_dir "${OUTPUT_DIR}" "${PACKAGE_ROOT}" cp -a -- "${STAGE_DIR}/." "${PACKAGE_ROOT}/" mkdir -p -- "${PACKAGE_ROOT}/DEBIAN" "${PACKAGE_ROOT}/usr/share/doc/rk1-media-stack" cp -- "${RKMEDIA_ROOT}/packaging/postinst" "${PACKAGE_ROOT}/DEBIAN/postinst" cp -- "${RKMEDIA_ROOT}/packaging/prerm" "${PACKAGE_ROOT}/DEBIAN/prerm" cp -- "${RKMEDIA_ROOT}/packaging/postrm" "${PACKAGE_ROOT}/DEBIAN/postrm" chmod 0755 "${PACKAGE_ROOT}/DEBIAN/postinst" "${PACKAGE_ROOT}/DEBIAN/prerm" "${PACKAGE_ROOT}/DEBIAN/postrm" printf '/etc/rkmedia/kodi.env\n' > "${PACKAGE_ROOT}/DEBIAN/conffiles" # A collaborative workspace or permissive host umask must never make core # target directories such as /etc, /usr, or /opt group-writable via dpkg. find "${PACKAGE_ROOT}" -type d -exec chmod 0755 {} + find "${PACKAGE_ROOT}" -type f ! -perm /0111 -exec chmod 0644 {} + find "${PACKAGE_ROOT}" -type f -perm /0111 -exec chmod 0755 {} + if find "${PACKAGE_ROOT}" \( -type d -o -type f \) -perm /0022 -print -quit \ | grep -q .; then die "package contains a group/world-writable path" fi if [[ -n "${DEPENDS_FROM_DEB}" ]]; then DEPENDS_FROM_DEB="$(absolute_path "${DEPENDS_FROM_DEB}")" [[ -f "${DEPENDS_FROM_DEB}" ]] || die "dependency source package not found: ${DEPENDS_FROM_DEB}" shlib_depends="$(dpkg-deb --field "${DEPENDS_FROM_DEB}" Depends)" [[ -n "${shlib_depends}" ]] || die "upstream package has an empty Depends field" else analysis_root="${OUTPUT_DIR}/shlibdeps" reset_child_dir "${OUTPUT_DIR}" "${analysis_root}" mkdir -p -- "${analysis_root}/debian" cat > "${analysis_root}/debian/control" <<'EOF' Source: rk1-media-stack Section: video Priority: optional Package: rk1-media-stack Architecture: arm64 Description: temporary metadata for dpkg-shlibdeps EOF elf_files=() while IFS= read -r -d '' candidate; do if file --brief "${candidate}" | grep -q '^ELF '; then elf_files+=("${candidate}") fi done < <(find "${PACKAGE_ROOT}/opt/rkmedia" -type f -print0) ((${#elf_files[@]} > 0)) || die "no ELF files found in media stage" pushd "${analysis_root}" >/dev/null shlib_output="$(dpkg-shlibdeps --ignore-missing-info -O \ -l"${PACKAGE_ROOT}/opt/rkmedia/lib" "${elf_files[@]}")" popd >/dev/null shlib_depends="${shlib_output#shlibs:Depends=}" [[ -n "${shlib_depends}" && "${shlib_depends}" != "${shlib_output}" ]] \ || die "dpkg-shlibdeps did not produce runtime dependencies" fi depends="adduser, systemd, udev, ${shlib_depends}" installed_size="$(du -sk "${PACKAGE_ROOT}" | awk '{print $1}')" if [[ -f "${PACKAGE_ROOT}/usr/share/doc/rk1-media-stack/upstream-deb.lock.json" ]]; then provenance_file="${PACKAGE_ROOT}/usr/share/doc/rk1-media-stack/upstream-deb.lock.json" else provenance_file="${PACKAGE_ROOT}/usr/share/doc/rk1-media-stack/sources.lock.json" fi lock_sha256="$(sha256sum "${provenance_file}" | awk '{print $1}')" sed \ -e "s/@VERSION@/${PACKAGE_VERSION}/g" \ -e "s/@INSTALLED_SIZE@/${installed_size}/g" \ -e "s/@LOCK_SHA256@/${lock_sha256}/g" \ -e "s/@DEPENDS@/${depends}/g" \ "${RKMEDIA_ROOT}/packaging/control.in" > "${PACKAGE_ROOT}/DEBIAN/control" pushd "${PACKAGE_ROOT}" >/dev/null find etc opt usr -type f -print0 \ | sort -z \ | xargs -0 md5sum > DEBIAN/md5sums popd >/dev/null if find "${PACKAGE_ROOT}" \( -type d -o -type f \) -perm /0022 -print -quit \ | grep -q .; then die "package contains a group/world-writable path after metadata generation" fi output_deb="${OUTPUT_DIR}/rk1-media-stack_${PACKAGE_VERSION}_arm64.deb" rm -f -- "${output_deb}" SOURCE_DATE_EPOCH="$(jq -er '.source_date_epoch' "${RKMEDIA_ROOT}/sources.lock.json")" \ dpkg-deb --root-owner-group --build "${PACKAGE_ROOT}" "${output_deb}" ( cd "${OUTPUT_DIR}" sha256sum "$(basename -- "${output_deb}")" \ >"$(basename -- "${output_deb}").sha256" ) dpkg-deb --info "${output_deb}" >/dev/null log "created ${output_deb}"