site  contact  subhomenews

dpkg db ro and rw layers synchronized

August 21, 2025 — BarryK

I posted about sync'ing PKGget with APT earlier today:

...but that sync code is far from complete.

When easyOS is updated to a new version, there will be a mismatch of the dpkg database information in /var/lib/dpkg/info and /var/lib/dpkg/status, on the read-write and read-only aufs levels.

That is, the above-mentioned folders and files get saved in /mnt/wkg/.session at power-off, reloaded at next bootup. You install a .deb, fine, it gets added into the dpkg database, and also saved in .session.

However, when you bootup a new version of Easy, the dpkg database information in /var/lib/dpkg in easy.sfs will no longer match what is in .session. There may be a package that was in easy.sfs, but no longer. Or, the latest easy.sfs may have a new package. Or, a package in easy.sfs may be a new version.

All of this information at the easy.sfs level is hidden, because the .session folder is on top, in the aufs layers. When you run various tests, there will be mismatches reported, for example:

# dpkg --audit
# /usr/bin/apt list --upgradable

I have written a script that handles all of these situations and sync's the dpkg database at the top layer with the easy.sfs layer. There is a new script, /var/local/petget/alias/sync-dpkg-layers:

#!/bin/bash
#bootup new version of easyos, there will be discrepancies between /var/lib/dpkg
#in /mnt/wkg/.session (and in containers .session) and in easy.sfs
#--new or removed pkgs in easy.sfs, version changes.

export LANG=C
mkdir -p /tmp/petget

#mismatch could be the 'status' files...
RWstatus="$(grep '^Package: ' /var/lib/dpkg/status | cut -f 2 -d ' ' | sort)"
ROstatus="$(grep '^Package: ' /mnt/.easy_ro/easy_sfs/var/lib/dpkg/status | cut -f 2 -d ' ' | sort)"

echo -n "$RWstatus" > /tmp/petget/dpkg-RWstatus
echo -n "$ROstatus" > /tmp/petget/dpkg-ROstatus

#find pkgs in rw layer, not in ro...
NEWstatus="$(grep -v -F -x -f /tmp/petget/dpkg-ROstatus /tmp/petget/dpkg-RWstatus)"
#ex:
#attr
#debootstrap
#gir1.2-ayatanaappindicator3-0.1
#grub-common
#libayatana-appindicator3-1
#libayatana-ido3-0.4-0
#libayatana-indicator3-7
#libdbusmenu-glib4
#libdbusmenu-gtk3-4
#memtest86+
#...some of these are user-installed, some no longer in easy.sfs

MISSstatus="$(grep -v -F -x -f /tmp/petget/dpkg-RWstatus /tmp/petget/dpkg-ROstatus)"
#ex:
#ccrypt
#firmware-intel-sound
#geany
#geany-common
#libaudio2
#libdaemon0
#libgif7
#libglu1-mesa
#libglut3.12
#libimobiledevice-glue-1.0-0
#libmtp9t64
#libmtp-common
#libnma0
#libnma-common
#libnma-headers
#libnotify-bin
#libplist-2.0-4
#libturbojpeg0
#libusbmuxd-2.0-7
#mobile-broadband-provider-info
#network-manager-applet
#network-manager-gnome
#nm-connection-editor
#...these are new in easy.sfs

##############
#handle NEWstatus...
for aNEW in ${NEWstatus}
do
 -z "$aNEW" ] && continue
 grep -q -F "|${aNEW}|" /root/.packages/user-installed-packages
 $? -eq ] && continue
 #want to purge it from db, as no longer exists...
 sed -i "/^Package: ${aNEW}$/,/^$/d" /var/lib/dpkg/status
 rm -f /var/lib/dpkg/info/${aNEW}:* 2>/dev/null
 rm -f /var/lib/dpkg/info/${aNEW}.* 2>/dev/null
done

##############
#handle MISSstatus...
for aMISS in ${MISSstatus}
do
 -z "$aMISS" ] && continue
 #extract paragraph from ro-layer, append on rw-layer...
 P1="$(sed -n "/^Package: ${aMISS}$/,/^$/p" /mnt/.easy_ro/easy_sfs/var/lib/dpkg/status)"
 echo "${P1}
>> /var/lib/dpkg/status
done

####################################
#handle pkg version change...
ROpkgs="$(grep -E '^Package: |^Version: |^$' /mnt/.easy_ro/easy_sfs/var/lib/dpkg/status | cut -f 2 -d ' ' | sed -e 's%^$%ZZZZZ%' | tr '\n' '|' | sed -e 's%|ZZZZZ|%\n%g')"
#...ex: xserver-xorg-video-vmware|1:13.4.0-1

for aP in ${ROpkgs}
do
 -z "$aP" ] && continue
 Pn="${aP%|*}"
 Pv="${aP#*|}"
 RWpara="$(sed -n "/^Package: ${Pn}$/,/^$/p" /var/lib/dpkg/status)"
 grep -q "^Version: ${Pv}$" <<<"$RWpara"
 if $? -ne ];then
  #top-level status file has wrong version...
  sed -i "/^Package: ${Pn}$/,/^$/d" /var/lib/dpkg/status
  ROpara="$(sed -n "/^Package: ${Pn}$/,/^$/p" /mnt/.easy_ro/easy_sfs/var/lib/dpkg/status)"
  echo "${ROpara}
>> /var/lib/dpkg/status
  #also the info files...
  rm -f /var/lib/dpkg/info/${Pn}:* 2>/dev/null
  rm -f /var/lib/dpkg/info/${Pn}.* 2>/dev/null
  cp -a -f /mnt/.easy_ro/easy_sfs/var/lib/dpkg/info/${Pn}:* /var/lib/dpkg/info2>/dev/null
  cp -a -f /mnt/.easy_ro/easy_sfs/var/lib/dpkg/info/${Pn}.* /var/lib/dpkg/info2>/dev/null
 fi
done

sync
###end###

It only gets called when there is an update of EasyOS version. Called from apt and apt-get alias scripts, and when PKGget starts, so will also work in containers.

The above code is the first version, to show the idea. I will work on it a bit more, for example to handle more .sfs files in the layers, such as the devx .sfs   

Tags: easy