Martin's bin/58697 made me look at postinstall again, which reminded
me that _obsolete_libs has an awk script that is unnecessarily opaque
(with variable names like "res", "result", "line", a function "digit"
that actually returns a number, not necessarily single-digit, etc).
Since I had to dig into that awk script anyway, I thought it might be
a good time to fix it, so that I don't need to re-do that work of
untabgling it the next time.

While there, I noticed that Christos attempt to protect new old libs
when downgrading never really worked b/c it filters by filename, but
the awk script emits absolute pathnames.

Here's the patch, only very lightly tested.  It's a context diff, b/c
the unfied version is not very readable.

Feedback is welcome.


*** postinstall.in.~1.63.~      2024-04-27 02:31:54.577307347 +0300
--- postinstall.in      2024-09-27 00:19:43.813013871 +0300
***************
*** 608,664 ****
  
        (
  
!       if [ ! -e "${DEST_DIR}/${dir}" ]
!       then
!               return 0
!       fi
! 
        cd "${DEST_DIR}/${dir}" || err 2 "can't cd to ${DEST_DIR}/${dir}"
!       echo lib*.so.* \
!       | tr ' ' '\n' \
!       | ${AWK} -v LibDir="${dir}/" '
  #{
  
! function digit(v, c, n) { return (n <= c) ? v[n] : 0 }
  
! function checklib(results, line, regex) {
!       if (! match(line, regex))
                return
!       lib = substr(line, RSTART, RLENGTH)
!       rev = substr($0, RLENGTH+1)
!       if (! (lib in results)) {
!               results[lib] = rev
                return
        }
!       orevc = split(results[lib], orev, ".")
!       nrevc = split(rev, nrev, ".")
!       maxc = (orevc > nrevc) ? orevc : nrevc
!       for (i = 1; i <= maxc; i++) {
!               res = digit(orev, orevc, i) - digit(nrev, nrevc, i)
!               if (res < 0) {
!                       print LibDir lib results[lib]
!                       results[lib] = rev
                        return
!               } else if (res > 0) {
!                       print LibDir lib rev
                        return
                }
        }
  }
  
! /^lib.*\.so\.[0-9]+\.[0-9]+(\.[0-9]+)?(\.debug)?$/ {
!       if (AllLibs)
!               checklib(minor, $0, "^lib.*\\.so\\.")
!       else
!               checklib(found, $0, "^lib.*\\.so\\.[0-9]+\\.")
! }
! 
! /^lib.*\.so\.[0-9]+$/ {
!       if (AllLibs)
!               checklib(major, $0, "^lib.*\\.so\\.")
! }
! 
! #}' | exclude_libs
  
        )
  }
--- 608,693 ----
  
        (
  
!       [ -e "${DEST_DIR}/${dir}" ] || return 0
        cd "${DEST_DIR}/${dir}" || err 2 "can't cd to ${DEST_DIR}/${dir}"
! 
!       # TODO: make this selectable with a command line option?
!       local maybe_purge_major
!       #maybe_purge_major='-v PurgeOldMajor=1'
! 
!       printf '%s\n' lib*.so.* | ${AWK} ${maybe_purge_major} '
  #{
  
! BEGIN {
!       BASE_REGEX  = "^lib.*\\.so\\."
!       MAJOR_REGEX = (BASE_REGEX "[0-9]+\\.")
! 
!       # in the usual case different major versions of the same
!       # library are considered different stems and do not compete
!       # with each other, we keep one of each, but you may request to
!       # purge old majors, in which case all versions compete for the
!       # single basename stem
!       if (PurgeOldMajor)
!               keepone = BASE_REGEX
!       else
!               keepone = MAJOR_REGEX
! }
! 
! # major version symlink
! PurgeOldMajor && /^lib.*\.so\.[0-9]+$/ {
!       checklib(major, $0, BASE_REGEX)
! }
! 
! # specific minor version of a library
! /^lib.*\.so\.[0-9]+\.[0-9]+(\.[0-9]+)?(\.debug)?$/ {
!       checklib(minor, $0, keepone)
! }
  
! function checklib(latest, libname, stem_regex) {
!       if (! match(libname, stem_regex))
                return
!       stem = substr(libname, RSTART, RLENGTH)
!       vers = substr(libname, RLENGTH + 1)
! 
!       # first time we see this stem? just record the version
!       if (! (stem in latest)) {
!               latest[stem] = vers
                return
        }
! 
!       # split version suffixes into the list of numeric components
!       oversc = split(latest[stem], overs, ".")
!       nversc = split(vers,         nvers, ".")
!       maxc = (oversc > nversc) ? oversc : nversc
! 
!       # is the new version "later" than the one we have seen?
!       for (i = 1; i <= maxc; ++i) {
!               cmp = (overs[i]+0) - (nvers[i]+0)
! 
!               if (cmp < 0) {
!                       # the one we have seen is older, so report it
!                       # as obsolete and update the latest seen
!                       # version to this new one
!                       print stem latest[stem]
!                       latest[stem] = vers
                        return
!               }
!               else if (cmp > 0) {
!                       # the one we have just read is older than the
!                       # one we have seen previously, so report this
!                       # "new" one as obsolete
!                       print libname
                        return
                }
        }
  }
  
!       # the ouput if further filtered by exclude_libs that protects
!       # libraries that have symlinks pointing to them, which one
!       # encounters when downgrading
! #}'   \
!       | exclude_libs \
!       | ${SED} "s|^|${dir}/|"
  
        )
  }

-uwe

Reply via email to