SYSTEM PM2 PATCHES, IMPLEMENTATION EXAMPLE
In applying this Patch Manager
patch, two cases arises
case #1: cacerts_gps
folder exists
[root@sfos ~]# ls -al /system/etc/security/cacerts_gps
isrgrootx1.pem -> /tmp/patchmanager/.../isrgrootx1.pem
roots.pem -> /tmp/patchmanager/.../roots.pem
case #2: cacerts_gps
folder does not exist
[root@sfos ~]# ls -al /system/etc/security/cacerts_gps
cacerts_gps -> /tmp/patchmanager/system/etc/security/cacerts_gps
Both case are wrong because Patch Manager
creates symlink where it was supposed to create dirs and files. In fact, symlinks are not the same story because some tools that operate on the filesystem required a specific option to follow symlinks. Like old versions of the tar
and tar
is one of the widely used tool for doing backups. The approach can be easily changed following these examples:
mkdir /tmp/test
cd /tmp/test
repourl="coderus.openrepos.net/media/documents"
tarball="robang74-x10ii-iii-agps-config-emea-0.2.0.tar.gz"
curl https://$repourl/$tarball | tar xvzf -
The following shell code will works with -p0
and with -p1
because the sed
regex
deal with /var
, new/var
and ./new/var
indifferently and every relative filepath
is converted into an absolute /filepath
.
files=$(sed -ne "s,^+++ *\.*[^/]*\([^ ]*\).*,/\\1,p" unified_diff.patch)
grep -qe "^+++ */" unified_diff.patch || false
plvl=$?
Now it is time to do a backup, for future restore but remember that overlay tricks the old tar
, therefore a recent tar
or busybox
tar
is needed
busybox tar czf /$store_dirpath/patch-$project_name.tar.gz $files
echo "$files" > /$store_dirpath/patch-$project_name.list
This determines the uninstall procedure by defining a global non-parametric function
patch_uninstall() {
rm -f $(cat /$store_dirpath/patch-$project_name.list)
busybox tar xzf /$store_dirpath/patch-$project_name.tar.gz -C /
}
This is useful before apply the diff
patch in order to creates dir and files not symlinks, therefore the symlinks engine could be ignored
patch_apply() {
ret=0
for i in $files; do mkdir -p $(basename $i); touch $i; done
if ! patch -d / $pagrs -p$plvl unified_diff.patch; then
patch_uninstall
ret=$((1+$?))
fi
return $ret
}
Is a system patch? For example system_diff.patch
instead of unified_diff.patch
? No, then uninstall at shutdown time. But why uninstall a patch at shutdown time with the risk that shutdown procedure and the related uninstall procedure can be interupped by a user physical keys controlled switch off? Because the filesystem for UI patches is volatile by default? Also the root filesystem about the reboot? Anyway:
num=$(printf "%05d" $(ls -1 /$store_dirpath/[0-9]*.tgz | wc -l))
busybox tar czf /$store_dirpath/$num-$project_name_applied.tar.gz $files
At boot time, in something functionally equivalent to /etc/rc.local
but after all system device has been mounted not just those in /etc/fstab
but before every systemd
service will start, will be inserted the restoring procedure which will applies all the patch in their correct sequence
files=$(ls -1 /$store_dirpath/[0-9]*_applied.tar.gz)
test "$files" = "" && exit 0
for i in $files; do busybox tar xzf $i -C /; done
That’s all, unless I forgot or overlooked something essential or important.
UPDATE #1
This seems promising to install system updates also for those that do not require a reboot:
system-update.target, system-update-pre.target, system-update-cleanup.service A special target unit that is used for offline system updates. systemd-system-update-generator(8) will redirect the boot process to this target if /system-update or /etc/system-update exists. For more information see systemd.offline-updates(7).
It seems a general solution that requires - by documentation - a reboot but the reboot is managed by the configuration and not automatically enforced. However, due to its specific nature and delicacy, it can be a better option to add a service ordering related to system-update.target
or even better system-update-pre.target
in such a way that the patches which might conflicts with package updates will be applied before making them fail, as expected to be, instead of being overwritten.
UPDATE #2
The Patch Manager
patches can be applied and unapplied many times during a user session and this is great feature . However, changing the way in which the PM2
works some of them might not fall into this category.
For example DNS Alternative is delivered like a RPM
and it proobably it is the best way to have it. Before, it was a RPM
package a developer might develop a patch. In general the way of providing a change could be exemplified in three main passages:
- system patch → 2. optional RPM package → 3. default RPM package
Which also implies three different level of integration with SFOS
: unsopported (community only), supported in terms of the repository consistency (community + Jolla) and Jolla supported (commercial support). Which three different level of SLA
and QoS
in terms of supporting the end-users.
IMHO, the main difference between a system patch and a RPM
package is bringing into the system new binaries rather than modify the system configuration. In this second case, having a system patch seems more reasonable expecially for the end-users that can choose to reconfigure the system as they wish - in the same manner they are doing with UI
.
While UI
patches can requires an application retart and a fingerprinter reader patch is functionally identical to a patch for e.g. the Settings, those have impact to the network and rely on the installation of 3rd party package e.g. dnsmasq need a little more attention. In fact, restarting network by SailFish Utilities
do not consider the case in which dnsmasq is installed and configured (to fix). For all the others, a reboot is almost necessary.
This brings us to the conclusion that there are three patches classes:
- those changes
UI
, app, stand-alone services level: easy to restart - those changes complex services like network/d-bus: might or might not be restarted
- those changes the system at such level that a reboot is needed: restart useless
The #1 and the #3 are almost straightforward cases to deal with. The second is a matter of policy: dnsmasq is optional but supported by network restart because it is an important feature that users usually requires to enable. Or on the other side is a 3rd party unsupported services an then the end-user needs to reboot his/her smartphone.