Skip to content

Commit cc176eb

Browse files
roliver-rpitdewey-rpi
authored andcommitted
Add rpi-package-download service
Signed-off-by: Richard Oliver <[email protected]>
1 parent a94c61b commit cc176eb

File tree

4 files changed

+127
-0
lines changed

4 files changed

+127
-0
lines changed

nfpm.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ depends:
140140
- curl
141141
- bash
142142
- gzip
143+
- dctrl-tools
144+
- diffutils
145+
- findutils
143146

144147
# Recommended packages. (overridable)
145148
# This will expand any env var you set in the field, e.g. ${RECOMMENDS_BLA}
@@ -219,6 +222,12 @@ contents:
219222
- src: fetch-repo-package-list/fetch-repo-package-list
220223
dst: /usr/local/bin/fetch-repo-package-list
221224

225+
- src: rpi-package-download/rpi-package-download.service
226+
dst: /usr/local/lib/systemd/system/[email protected]
227+
228+
- src: rpi-package-download/rpi-package-download
229+
dst: /usr/local/bin/rpi-package-download
230+
222231
# This will add all files in some/directory or in subdirectories at the
223232
# same level under the directory /etc. This means the tree structure in
224233
# some/directory will not be replicated.

rpi-package-download/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# rpi-package-download
2+
A oneshot service to download the latest version of a Raspberry Pi OS package
3+
(using a previously fetched package list). The latest package information is
4+
also available in dctrl format.
5+
6+
## Usage
7+
To download the latest version of the alsa-utils package:
8+
```
9+
systemctl start rpi-package-download@$(systemd-escape alsa-utils).service
10+
```
11+
12+
The service makes use of systemd's CacheDirectory during execution. The latest
13+
package can be found by following symlinks in the CacheDirectory which would
14+
typically be as follows for the above example:
15+
```
16+
/var/cache/rpi-package-download@alsa\x2dutils.service/latest/package.deb
17+
```
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
# Usage: rpi-package-download <systemd escaped package>
6+
# e.g. rpi-package-download 'alsa-utils'
7+
# would download alsa-utils
8+
9+
# deps:
10+
# - dctrl-tools (grep-dctrl)
11+
# - coreutils (mktemp,cut,sha1sum,sha256sum)
12+
# - diffutils (cmp)
13+
# - findutils (xargs)
14+
# - curl
15+
16+
REQUESTED_PACKAGE="${1}"
17+
18+
REPOSITORY="${REPOSITORY:-https://archive.raspberrypi.org/debian}"
19+
RELEASE="${RELEASE:-bookworm}"
20+
ARCH="${ARCH:-arm64}"
21+
22+
# Should be set by systemd
23+
SERVICE_NAME="rpi-package-download@$(systemd-escape ${REQUESTED_PACKAGE}).service"
24+
CACHE_DIRECTORY="${CACHE_DIRECTORY:=/var/cache/${SERVICE_NAME}}"
25+
RUNTIME_DIRECTORY="${RUNTIME_DIRECTORY:=/run/${SERVICE_NAME}}"
26+
27+
# Assume that [email protected] RUNTIME_DIRECTORY is available relative to our RUNTIME_DIRECTORY
28+
PACKAGES_FILE="${RUNTIME_DIRECTORY}/../fetch-repo-package-list@$(systemd-escape ${REPOSITORY}).service/Packages"
29+
30+
>&2 echo "Getting latest package information for ${REQUESTED_PACKAGE}"
31+
TMP_PKG_FILE="$(mktemp --tmpdir rpi-package-downloader.XXX)"
32+
33+
grep-dctrl \
34+
--field=Package \
35+
--exact-match "${REQUESTED_PACKAGE}" \
36+
"${PACKAGES_FILE}" \
37+
> ${TMP_PKG_FILE}
38+
39+
LATEST_DIR="${RUNTIME_DIRECTORY}/latest"
40+
LATEST_PKG_FILE="${LATEST_DIR}/Package"
41+
42+
if cmp ${TMP_PKG_FILE} ${LATEST_PKG_FILE} 2>/dev/null; then
43+
>&2 echo "Package up-to-date; nothing to do"
44+
exit
45+
fi
46+
47+
CHKSUM=$(sha1sum ${TMP_PKG_FILE} | cut -d " " -f 1)
48+
WORK_DIR="${CACHE_DIRECTORY}/${CHKSUM}"
49+
mkdir -p $WORK_DIR
50+
PACKAGE_FILE="${WORK_DIR}/Packages"
51+
mv "$TMP_PKG_FILE" "$PACKAGE_FILE"
52+
53+
function get_dctrl_field() {
54+
grep-dctrl \
55+
--field=Package \
56+
--exact-match "${1}" \
57+
--no-field-names \
58+
--show-field="${2}" \
59+
"${PACKAGE_FILE}"
60+
}
61+
62+
PACKAGE_PARTIAL_URL="$(get_dctrl_field ${REQUESTED_PACKAGE} Filename)"
63+
PACKAGE_FULL_URL="${REPOSITORY}/${PACKAGE_PARTIAL_URL}"
64+
PACKAGE_BASENAME="$(basename ${PACKAGE_PARTIAL_URL})"
65+
66+
>&2 echo "Downloading package"
67+
curl \
68+
"${PACKAGE_FULL_URL}" \
69+
-o "${WORK_DIR}/${PACKAGE_BASENAME}" \
70+
2> /dev/null
71+
72+
>&2 echo -n "Verifying package checksum: "
73+
pushd "${WORK_DIR}" > /dev/null
74+
grep-dctrl \
75+
--field=Package \
76+
--exact-match "${REQUESTED_PACKAGE}" \
77+
--show-field=SHA256,Filename \
78+
--no-field-names \
79+
"${PACKAGE_FILE}" | sed 's/.*\///' | xargs > "${PACKAGE_BASENAME}.sha256"
80+
81+
sha256sum --check "${PACKAGE_BASENAME}".sha256
82+
popd > /dev/null
83+
84+
>&2 echo "Updating symlinks"
85+
ln -sf "${WORK_DIR}/${PACKAGE_BASENAME}" "${WORK_DIR}/package.deb"
86+
ln -sf "${WORK_DIR}" "${CACHE_DIRECTORY}/latest"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[Unit]
2+
Description=Downloads specified Raspberry Pi OS package
3+
After=fetch-repo-package-list@https:--archive.raspberrypi.org-debian.service
4+
5+
[Service]
6+
Type=oneshot
7+
Environment=REPOSITORY="https://archive.raspberrypi.org/debian"
8+
EnvironmentFile=/etc/rpi-sb-provisioner/config
9+
ExecStart=/usr/local/bin/rpi-package-download "%I"
10+
CacheDirectory=%n
11+
RuntimeDirectory=%n
12+
RuntimeDirectoryPreserve=true
13+
14+
[Install]
15+
WantedBy=multi-user.target

0 commit comments

Comments
 (0)