From fb13f7fd9eff012cb7b9dbf94ac5381c69404055 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 9 Feb 2022 14:47:14 +0200
Subject: [PATCH] Add optional callback on directory changes during rpmfi
 iteration

Conflict:adapt rpmfi.c because 318efbaec is not merged.
Reference:https://github.com/rpm-software-management/rpm/commit/fb13f7fd9eff012cb7b9dbf94ac5381c69404055

Internal only for now in case we need to fiddle with the API some more,
but no reason this couldn't be made public later.
---
 lib/rpmfi.c          | 24 +++++++++++++++++++++++-
 lib/rpmfi_internal.h | 17 +++++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index 4673fbb85..e8e7d08bf 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -55,6 +55,9 @@ struct rpmfi_s {
     int intervalStart;		/*!< Start of iterating interval. */
     int intervalEnd;		/*!< End of iterating interval. */
 
+    rpmfiChdirCb onChdir;	/*!< Callback for directory changes */
+    void *onChdirData;		/*!< Caller private callback data */
+
     rpmfiles files;		/*!< File info set */
     rpmcpio_t archive;		/*!< Archive with payload */
     unsigned char * found;	/*!< Bit field of files found in the archive */
@@ -303,6 +306,17 @@ rpm_count_t rpmfiDC(rpmfi fi)
 }
 #endif
 
+int rpmfiSetOnChdir(rpmfi fi, rpmfiChdirCb cb, void *data)
+{
+    int rc = -1;
+    if (fi != NULL) {
+	fi->onChdir = cb;
+	fi->onChdirData = data;
+	rc = 0;
+    }
+    return rc;
+}
+
 int rpmfiFX(rpmfi fi)
 {
     return (fi != NULL ? fi->i : -1);
@@ -313,9 +327,17 @@ int rpmfiSetFX(rpmfi fi, int fx)
     int i = -1;
 
     if (fi != NULL && fx >= 0 && fx < rpmfilesFC(fi->files)) {
+	int dx = fi->j;
+	i = fi->i;
 	fi->i = fx;
 	fi->j = rpmfilesDI(fi->files, fi->i);
 	i = fi->i;
+
+	if (fi->j != dx && fi->onChdir) {
+	    int chrc = fi->onChdir(fi, fi->onChdirData);
+	    if (chrc < 0)
+		i = chrc;
+	}
     }
     return i;
 }
@@ -1780,9 +1802,9 @@ static rpmfi initIter(rpmfiles files, int itype, int link)
     if (files && itype>=0 && itype<=RPMFILEITERMAX) {
 	fi = xcalloc(1, sizeof(*fi)); 
 	fi->i = -1;
+	fi->j = -1;
 	fi->files = link ? rpmfilesLink(files) : files;
 	fi->next = nextfuncs[itype];
-	fi->i = -1;
 	if (itype == RPMFI_ITER_BACK) {
 	    fi->i = rpmfilesFC(fi->files);
 	} else if (itype >=RPMFI_ITER_READ_ARCHIVE
diff --git a/lib/rpmfi_internal.h b/lib/rpmfi_internal.h
index dccc6ccbe..37f1d45f5 100644
--- a/lib/rpmfi_internal.h
+++ b/lib/rpmfi_internal.h
@@ -13,6 +13,23 @@
 extern "C" {
 #endif
 
+/** \ingroup rpmfi
+ * Callback on file iterator directory changes
+ * @param fi		file info
+ * @param data		caller private callback data
+ * @return		0 on success, < 0 on error (to stop iteration)
+ */
+typedef int (*rpmfiChdirCb)(rpmfi fi, void *data);
+
+/** \ingroup rpmfi
+ * Set a callback for directory changes during iteration.
+ * @param fi		file info
+ * @param cb		callback function
+ * @param data		caller private callback data
+ * @return		string pool handle (weak reference)
+ */
+int rpmfiSetOnChdir(rpmfi fi, rpmfiChdirCb cb, void *data);
+
 /** \ingroup rpmfi
  * Return file info set string pool handle
  * @param fi		file info
-- 
2.27.0

