github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/tools/make_apt.sh (about) 1 #!/bin/bash 2 3 # Copyright 2018 The gVisor Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 if [[ "$#" -le 3 ]]; then 18 echo "usage: $0 <private-key> <suite> <root> <packages...>" 19 exit 1 20 fi 21 declare private_key 22 declare suite 23 declare root 24 private_key="$(readlink -e "$1")" 25 suite="$2" 26 root="$(readlink -m "$3")" 27 readonly private_key 28 readonly suite 29 readonly root 30 shift; shift; shift # For "$@" below. 31 32 # Ensure that we have the correct packages installed. 33 function apt_install() { 34 while true; do 35 sudo apt-get update && 36 sudo apt-get install -y "$@" && 37 true 38 result="${?}" 39 case $result in 40 0) 41 break 42 ;; 43 100) 44 # 100 is the error code that apt-get returns. 45 ;; 46 *) 47 exit $result 48 ;; 49 esac 50 done 51 } 52 dpkg-sig --help >/dev/null 2>&1 || apt_install dpkg-sig 53 apt-ftparchive --help >/dev/null 2>&1 || apt_install apt-utils 54 xz --help >/dev/null 2>&1 || apt_install xz-utils 55 56 # Verbose from this point. 57 set -xeo pipefail 58 59 # Create a directory for the release. 60 declare -r release="${root}/dists/${suite}" 61 mkdir -p "${release}" 62 63 # Create a temporary keyring, and ensure it is cleaned up. 64 # Using separate homedir allows us to install apt repositories multiple times 65 # using the same key. This is a limitation in GnuPG pre-2.1. 66 declare keyring 67 declare homedir 68 declare gpg_opts 69 keyring="$(mktemp /tmp/keyringXXXXXX.gpg)" 70 homedir="$(mktemp -d /tmp/homedirXXXXXX)" 71 gpg_opts=("--no-default-keyring" "--secret-keyring" "${keyring}" "--homedir" "${homedir}") 72 readonly keyring 73 readonly homedir 74 readonly gpg_opts 75 cleanup() { 76 rm -rf "${keyring}" "${homedir}" 77 } 78 trap cleanup EXIT 79 80 # We attempt the import twice because the first one will fail if the public key 81 # is not found. This isn't actually a failure for us, because we don't require 82 # the public key (this may be stored separately). The second import will succeed 83 # because, in reality, the first import succeeded and it's a no-op. 84 gpg "${gpg_opts[@]}" --import "${private_key}" || \ 85 gpg "${gpg_opts[@]}" --import "${private_key}" 86 87 # Copy the packages into the root. 88 for pkg in "$@"; do 89 if ! [[ -f "${pkg}" ]]; then 90 continue 91 fi 92 ext=${pkg##*.} 93 if [[ "${ext}" != "deb" ]]; then 94 continue 95 fi 96 97 # Extract package information. 98 name=$(basename "${pkg}" ".${ext}") 99 arch=$(dpkg --info "${pkg}" | grep 'Architecture:' | cut -d':' -f2) 100 version=$(dpkg --info "${pkg}" | grep 'Version:' | cut -d':' -f2) 101 arch=${arch// /} # Trim whitespace. 102 version=${version// /} # Ditto. 103 destdir="${root}/pool/${version}/binary-${arch}" 104 105 # Copy & sign the package. 106 mkdir -p "${destdir}" 107 cp -a -L "$(dirname "${pkg}")/${name}.deb" "${destdir}" 108 cp -a -L "$(dirname "${pkg}")/${name}.changes" "${destdir}" 109 chmod 0644 "${destdir}"/"${name}".* 110 # Sign a package only if it isn't signed yet. 111 # We use [*] here to expand the gpg_opts array into a single shell-word. 112 dpkg-sig -g "${gpg_opts[*]}" --verify "${destdir}/${name}.deb" || 113 dpkg-sig -g "${gpg_opts[*]}" --sign builder "${destdir}/${name}.deb" 114 done 115 116 # Build the package list. 117 declare arches=() 118 for dir in "${root}"/pool/*/binary-*; do 119 name=$(basename "${dir}") 120 arch=${name##binary-} 121 arches+=("${arch}") 122 repo_packages="${release}"/main/"${name}" 123 mkdir -p "${repo_packages}" 124 (cd "${root}" && apt-ftparchive packages "${dir##${root}/}" > "${repo_packages}"/Packages) 125 if ! [[ -s "${repo_packages}"/Packages ]]; then 126 echo "Packages file is size zero." >&2 127 exit 1 128 fi 129 (cd "${repo_packages}" && cat Packages | gzip > Packages.gz) 130 (cd "${repo_packages}" && cat Packages | xz > Packages.xz) 131 done 132 133 # Build the release list. 134 cat > "${release}"/apt.conf <<EOF 135 APT { 136 FTPArchive { 137 Release { 138 Architectures "${arches[@]}"; 139 Suite "${suite}"; 140 Components "main"; 141 }; 142 }; 143 }; 144 EOF 145 (cd "${release}" && apt-ftparchive -c=apt.conf release . > Release) 146 rm "${release}"/apt.conf 147 148 # Sign the release. 149 declare -r digest_opts=("--digest-algo" "SHA512" "--cert-digest-algo" "SHA512") 150 (cd "${release}" && rm -f Release.gpg InRelease) 151 (cd "${release}" && gpg "${gpg_opts[@]}" --clearsign "${digest_opts[@]}" -o InRelease Release) 152 (cd "${release}" && gpg "${gpg_opts[@]}" -abs "${digest_opts[@]}" -o Release.gpg Release)