From 87becdafd641002f760e9671aa16cb1d1fd56fd6cd50526f8e8e30ecd2f2cb68 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20Schr=C3=B6der?= <mls@suse.com>
Date: Wed, 14 Feb 2018 09:47:53 +0000
Subject: [PATCH] - change disk usage handling to take hardlinks into account  
 [bnc#720150]

OBS-URL: https://build.opensuse.org/package/show/Base:System/rpm?expand=0&rev=439
---
 find-provides.ksyms |  81 ------------------------------
 find-requires.ksyms |  29 -----------
 findksyms.diff      | 120 +++++++++++++++++++++++++++++++++++++++++++-
 hardlinks.diff      |  60 ++++++++++++++++++++++
 rpm.changes         |   6 +++
 rpm.spec            |   9 ++--
 6 files changed, 187 insertions(+), 118 deletions(-)
 delete mode 100644 find-provides.ksyms
 delete mode 100644 find-requires.ksyms
 create mode 100644 hardlinks.diff

diff --git a/find-provides.ksyms b/find-provides.ksyms
deleted file mode 100644
index 5de8984..0000000
--- a/find-provides.ksyms
+++ /dev/null
@@ -1,81 +0,0 @@
-#! /bin/bash
-
-IFS=$'\n'
-
-is_opensuse=false
-
-if test "$1" = "--opensuse"; then
-    if test "$2" -gt 0; then
-        is_opensuse=true
-    fi
-    shift 2
-fi
-
-if ! $is_opensuse; then
-    trap 'rm -f "$tmp"' EXIT
-    tmp=$(mktemp)
-fi
-
-
-while read f; do
-    test -e "$f" || continue
-    is_module=""
-    case "$f" in
-    *.debug)
-        continue
-        ;;
-    */boot/vmlinu[xz]-*)
-        flavor=${f##*/vmlinu[xz]-}
-        flavor=${flavor%.gz}
-        echo "kernel-uname-r = $flavor"
-        version=${flavor}
-        flavor=${flavor##*-}
-        ;;
-    */lib/modules/*/*.ko | */lib/modules/*/*.ko.gz | */boot/vmlinu[xz]*)
-        is_module="1"
-        ;;
-    *)
-        continue
-    esac
-    if $is_opensuse; then
-        continue
-    fi
-    unzip=false
-    case "$f" in
-    *.gz | */boot/vmlinuz*)
-        unzip=true
-    esac
-    if $unzip && gzip -cd "$f" >"$tmp"; then
-        f=$tmp
-    fi
-    if test -z "$flavor" -a -n "$is_module" ; then
-        flavor=$(/sbin/modinfo -F vermagic "$f")
-        flavor=${flavor%% *}
-        version=${flavor}
-        flavor=${flavor##*-}
-    fi
-    if test -z "$flavor"; then
-        echo "warning: cannot determine kernel flavor from $(/sbin/modinfo -F vermagic "$f" 2>&1)" >&2
-        continue
-    fi
-    objdir=$(readlink /lib/modules/$version/build)
-    objdir_build=$RPM_BUILD_ROOT$(readlink $RPM_BUILD_ROOT/lib/modules/$version/build)
-    for i in $objdir_build $objdir ; do
-            ksym_provides=$i/scripts/mod/ksym-provides
-            [ -x $ksym_provides ] && break
-    done
-    if [ -x $ksym_provides ] ; then
-            $ksym_provides $flavor $f
-    else
-            major=${version%%.*}
-            sub=${version#*.}
-            sub=${sub%%.*}
-            if [ "$major" -ge 4 -a "$sub" -ge 10 ] ; then
-                    echo "error: cannot determine ksym provides of $f - missing ksym-povides tool." >&2
-            else
-                    nm "$f" \
-                            | sed -r -ne "s/^0*([0-9a-f]+) A __crc_(.+)/ksym($flavor:\\2) = \\1/p"
-            fi
-    fi
-done \
-| sort -u
diff --git a/find-requires.ksyms b/find-requires.ksyms
deleted file mode 100644
index ebb87be..0000000
--- a/find-requires.ksyms
+++ /dev/null
@@ -1,29 +0,0 @@
-#! /bin/bash
-
-IFS=$'\n'
-
-is_opensuse=false
-
-if test "$1" = "--opensuse"; then
-    if test "$2" -gt 0; then
-        is_opensuse=true
-    fi
-    shift 2
-fi
-
-if ! $is_opensuse && ! test -e /sbin/modprobe; then
-    cat > /dev/null
-    exit 0
-fi
-
-for f in $(grep -E '/lib/modules/.+\.ko$' | grep -v '/lib/modules/[^/]*/kernel/'); do
-    flavor=${f#*/lib/modules/}
-    flavor=${flavor%%/*}
-    if $is_opensuse; then
-        echo "kernel-uname-r = $flavor"
-        continue
-    fi
-    flavor=${flavor##*-}
-    /sbin/modprobe --dump-modversions "$f" \
-	    | sed -r -ne "s/^0x0*([0-9a-f]+)[[:blank:]]+(.+)/ksym($flavor:\\2) = \\1/p"
-done | sort -u
diff --git a/findksyms.diff b/findksyms.diff
index 3f9ce7f..2472f7d 100644
--- a/findksyms.diff
+++ b/findksyms.diff
@@ -1,5 +1,5 @@
---- ./scripts/Makefile.am.orig	2018-01-31 13:08:32.644956731 +0000
-+++ ./scripts/Makefile.am	2018-01-31 13:09:24.081819852 +0000
+--- ./scripts/Makefile.am.orig	2018-02-14 09:42:12.958726157 +0000
++++ ./scripts/Makefile.am	2018-02-14 09:43:26.605515718 +0000
 @@ -19,6 +19,7 @@ EXTRA_DIST = \
  	tgpg vpkg-provides.sh \
  	find-requires find-provides \
@@ -16,3 +16,119 @@
  	metainfo.prov \
  	mono-find-requires mono-find-provides \
  	pkgconfigdeps.sh libtooldeps.sh \
+--- ./scripts/find-provides.ksyms.orig	2018-02-14 09:42:54.757606752 +0000
++++ ./scripts/find-provides.ksyms	2018-02-14 09:42:39.165651303 +0000
+@@ -0,0 +1,81 @@
++#! /bin/bash
++
++IFS=$'\n'
++
++is_opensuse=false
++
++if test "$1" = "--opensuse"; then
++    if test "$2" -gt 0; then
++        is_opensuse=true
++    fi
++    shift 2
++fi
++
++if ! $is_opensuse; then
++    trap 'rm -f "$tmp"' EXIT
++    tmp=$(mktemp)
++fi
++
++
++while read f; do
++    test -e "$f" || continue
++    is_module=""
++    case "$f" in
++    *.debug)
++        continue
++        ;;
++    */boot/vmlinu[xz]-*)
++        flavor=${f##*/vmlinu[xz]-}
++        flavor=${flavor%.gz}
++        echo "kernel-uname-r = $flavor"
++        version=${flavor}
++        flavor=${flavor##*-}
++        ;;
++    */lib/modules/*/*.ko | */lib/modules/*/*.ko.gz | */boot/vmlinu[xz]*)
++        is_module="1"
++        ;;
++    *)
++        continue
++    esac
++    if $is_opensuse; then
++        continue
++    fi
++    unzip=false
++    case "$f" in
++    *.gz | */boot/vmlinuz*)
++        unzip=true
++    esac
++    if $unzip && gzip -cd "$f" >"$tmp"; then
++        f=$tmp
++    fi
++    if test -z "$flavor" -a -n "$is_module" ; then
++        flavor=$(/sbin/modinfo -F vermagic "$f")
++        flavor=${flavor%% *}
++        version=${flavor}
++        flavor=${flavor##*-}
++    fi
++    if test -z "$flavor"; then
++        echo "warning: cannot determine kernel flavor from $(/sbin/modinfo -F vermagic "$f" 2>&1)" >&2
++        continue
++    fi
++    objdir=$(readlink /lib/modules/$version/build)
++    objdir_build=$RPM_BUILD_ROOT$(readlink $RPM_BUILD_ROOT/lib/modules/$version/build)
++    for i in $objdir_build $objdir ; do
++            ksym_provides=$i/scripts/mod/ksym-provides
++            [ -x $ksym_provides ] && break
++    done
++    if [ -x $ksym_provides ] ; then
++            $ksym_provides $flavor $f
++    else
++            major=${version%%.*}
++            sub=${version#*.}
++            sub=${sub%%.*}
++            if [ "$major" -ge 4 -a "$sub" -ge 10 ] ; then
++                    echo "error: cannot determine ksym provides of $f - missing ksym-povides tool." >&2
++            else
++                    nm "$f" \
++                            | sed -r -ne "s/^0*([0-9a-f]+) A __crc_(.+)/ksym($flavor:\\2) = \\1/p"
++            fi
++    fi
++done \
++| sort -u
+--- ./scripts/find-requires.ksyms.orig	2018-02-14 09:43:00.437590470 +0000
++++ ./scripts/find-requires.ksyms	2018-02-14 09:42:45.621632854 +0000
+@@ -0,0 +1,29 @@
++#! /bin/bash
++
++IFS=$'\n'
++
++is_opensuse=false
++
++if test "$1" = "--opensuse"; then
++    if test "$2" -gt 0; then
++        is_opensuse=true
++    fi
++    shift 2
++fi
++
++if ! $is_opensuse && ! test -e /sbin/modprobe; then
++    cat > /dev/null
++    exit 0
++fi
++
++for f in $(grep -E '/lib/modules/.+\.ko$' | grep -v '/lib/modules/[^/]*/kernel/'); do
++    flavor=${f#*/lib/modules/}
++    flavor=${flavor%%/*}
++    if $is_opensuse; then
++        echo "kernel-uname-r = $flavor"
++        continue
++    fi
++    flavor=${flavor##*-}
++    /sbin/modprobe --dump-modversions "$f" \
++	    | sed -r -ne "s/^0x0*([0-9a-f]+)[[:blank:]]+(.+)/ksym($flavor:\\2) = \\1/p"
++done | sort -u
diff --git a/hardlinks.diff b/hardlinks.diff
new file mode 100644
index 0000000..2013116
--- /dev/null
+++ b/hardlinks.diff
@@ -0,0 +1,60 @@
+--- lib/rpmfiles.h.orig
++++ lib/rpmfiles.h
+@@ -156,7 +156,7 @@ typedef rpmFlags rpmfiFlags;
+ 
+ #define RPMFI_FLAGS_ERASE \
+     (RPMFI_NOFILECLASS | RPMFI_NOFILELANGS | \
+-     RPMFI_NOFILEMTIMES | RPMFI_NOFILERDEVS | RPMFI_NOFILEINODES | \
++     RPMFI_NOFILEMTIMES | RPMFI_NOFILERDEVS | \
+      RPMFI_NOFILEVERIFYFLAGS)
+ 
+ #define RPMFI_FLAGS_INSTALL \
+--- lib/transaction.c.orig
++++ lib/transaction.c
+@@ -412,6 +412,8 @@ static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfiles fi, int fx
+ {
+     rpmfs fs = rpmteGetFileStates(p);
+     int isCfgFile = ((rpmfilesFFlags(otherFi, ofx) | rpmfilesFFlags(fi, fx)) & RPMFILE_CONFIG);
++    int nlink;
++    const int *links;
+ 
+     if (XFA_SKIPPING(rpmfsGetAction(fs, fx)))
+ 	return;
+@@ -481,7 +483,10 @@ static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfiles fi, int fx
+ 	}
+     }
+ 
+-    rpmfilesSetFReplacedSize(fi, fx, rpmfilesFSize(otherFi, ofx));
++    /* Only account for the last file of a hardlink set */
++    nlink = rpmfilesFLinks(otherFi, ofx, &links);
++    if (nlink <= 1 || links[nlink - 1] == ofx)
++	rpmfilesSetFReplacedSize(fi, fx, rpmfilesFSize(otherFi, ofx));
+ }
+ 
+ /**
+@@ -491,6 +496,7 @@ static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfiles fi, int fx
+ static void handleOverlappedFiles(rpmts ts, fingerPrintCache fpc, rpmte p, rpmfiles fi)
+ {
+     rpm_loff_t fixupSize = 0;
++    rpm_loff_t fileSize = 0;
+     int i, j;
+     rpmfs fs = rpmteGetFileStates(p);
+     rpmfs otherFs;
+@@ -675,9 +681,16 @@ assert(otherFi != NULL);
+ 	}
+ 	rpmfilesFree(otherFi);
+ 
++	fileSize = rpmfilesFSize(fi, i);
++	nlink = rpmfilesFLinks(fi, i, &links);
++	if (nlink > 1 && links[nlink - 1] != i) {
++	    /* Only account for the last file of a hardlink set */
++	    fileSize = 0;
++	    fixupSize = 0;
++	}
+ 	/* Update disk space info for a file. */
+ 	rpmtsUpdateDSI(ts, fpEntryDev(fpc, fiFps), fpEntryDir(fpc, fiFps),
+-		       rpmfilesFSize(fi, i), rpmfilesFReplacedSize(fi, i),
++		       fileSize, rpmfilesFReplacedSize(fi, i),
+ 		       fixupSize, rpmfsGetAction(fs, i));
+ 
+     }
diff --git a/rpm.changes b/rpm.changes
index 750d653..83618db 100644
--- a/rpm.changes
+++ b/rpm.changes
@@ -1,3 +1,9 @@
+-------------------------------------------------------------------
+Wed Feb 14 10:45:25 CET 2018 - mls@suse.de
+
+- change disk usage handling to take hardlinks into account
+  [bnc#720150]
+
 -------------------------------------------------------------------
 Wed Feb  7 17:23:48 UTC 2018 - msuchanek@suse.com
 
diff --git a/rpm.spec b/rpm.spec
index 1d0796f..b074fba 100644
--- a/rpm.spec
+++ b/rpm.spec
@@ -63,8 +63,6 @@ Source10:       beecrypt-4.1.2.tar.bz2
 Source11:       db-4.8.30.tar.bz2
 Source12:       baselibs.conf
 Source13:       rpmconfigcheck.service
-Source14:       find-provides.ksyms
-Source15:       find-requires.ksyms
 Patch1:         beecrypt-4.1.2.diff
 Patch2:         db.diff
 Patch3:         rpm-4.12.0.1-fix-bashisms.patch
@@ -132,6 +130,7 @@ Patch103:       find-lang-qt-qm.patch
 Patch108:       debugedit-macro.diff
 Patch109:       pythondistdeps.diff
 Patch111:       debugedit-bnc1076819.diff
+Patch112:       hardlinks.diff
 Patch6464:      auto-config-update-aarch64-ppc64le.diff
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 #
@@ -228,18 +227,16 @@ rm -f rpmdb/db.h
 %patch                               -P 85
 %patch                   -P 93 -P 94                         -P 99
 %patch -P 100        -P 102 -P 103                             -P 108
-%patch -P 109 -P 111
+%patch -P 109 -P 111 -P 112
 
 %ifarch aarch64 ppc64le
 %patch6464
 %endif
 
-cp %{SOURCE14} %{SOURCE15} scripts
-
 cp config.guess config.sub db/dist/
 cp config.guess config.sub beecrypt/
 #chmod 755 scripts/find-supplements{,.ksyms}
-chmod 755 scripts/find-provides.ksyms scripts/find-requires.ksyms
+#chmod 755 scripts/find-provides.ksyms scripts/find-requires.ksyms
 #chmod 755 scripts/firmware.prov
 #chmod 755 scripts/debuginfo.prov
 tar -xjvf %{SOURCE1}