|
|
9ceacf |
From 3a5d2ee0f56d049927c4dcdd03e8e275ac03e20d Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Mon, 8 Feb 2021 10:45:59 +0200
|
|
|
9ceacf |
Subject: [PATCH 01/10] Clean up file unpack iteration logic a bit
|
|
|
9ceacf |
|
|
|
9ceacf |
Handle rpmfiNext() in the while-condition directly to make it more like
|
|
|
9ceacf |
similar other constructs elsewhere, adjust for the end of iteration
|
|
|
9ceacf |
code after the loop. Also take the file index from rpmfiNext() so
|
|
|
9ceacf |
we don't need multiple calls to rpmfiFX() later.
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 19 +++++++------------
|
|
|
9ceacf |
1 file changed, 7 insertions(+), 12 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index 432bcbd90..f71b9bc1e 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -865,6 +865,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
struct stat sb;
|
|
|
9ceacf |
int saveerrno = errno;
|
|
|
9ceacf |
int rc = 0;
|
|
|
9ceacf |
+ int fx = -1;
|
|
|
9ceacf |
int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0;
|
|
|
9ceacf |
int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0;
|
|
|
9ceacf |
int firsthardlink = -1;
|
|
|
9ceacf |
@@ -886,17 +887,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
/* Detect and create directories not explicitly in package. */
|
|
|
9ceacf |
rc = fsmMkdirs(files, fs, plugins);
|
|
|
9ceacf |
|
|
|
9ceacf |
- while (!rc) {
|
|
|
9ceacf |
- /* Read next payload header. */
|
|
|
9ceacf |
- rc = rpmfiNext(fi);
|
|
|
9ceacf |
-
|
|
|
9ceacf |
- if (rc < 0) {
|
|
|
9ceacf |
- if (rc == RPMERR_ITER_END)
|
|
|
9ceacf |
- rc = 0;
|
|
|
9ceacf |
- break;
|
|
|
9ceacf |
- }
|
|
|
9ceacf |
-
|
|
|
9ceacf |
- action = rpmfsGetAction(fs, rpmfiFX(fi));
|
|
|
9ceacf |
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
|
|
9ceacf |
+ action = rpmfsGetAction(fs, fx);
|
|
|
9ceacf |
skip = XFA_SKIPPING(action);
|
|
|
9ceacf |
if (action != FA_TOUCH) {
|
|
|
9ceacf |
suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
|
|
9ceacf |
@@ -920,7 +912,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
if (rc) {
|
|
|
9ceacf |
skip = 1;
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
- setFileState(fs, rpmfiFX(fi));
|
|
|
9ceacf |
+ setFileState(fs, fx);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
if (!skip) {
|
|
|
9ceacf |
@@ -1022,6 +1014,9 @@ touch:
|
|
|
9ceacf |
fpath = _free(fpath);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
+ if (!rc && fx != RPMERR_ITER_END)
|
|
|
9ceacf |
+ rc = fx;
|
|
|
9ceacf |
+
|
|
|
9ceacf |
rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS), fdOp(payload, FDSTAT_READ));
|
|
|
9ceacf |
rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST), fdOp(payload, FDSTAT_DIGEST));
|
|
|
9ceacf |
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From 3096acbddc57eb2b65c96aad1ed3524ea9d0cead Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Wed, 10 Feb 2021 08:25:28 +0200
|
|
|
9ceacf |
Subject: [PATCH 02/10] Drop unused filename variable
|
|
|
9ceacf |
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 2 --
|
|
|
9ceacf |
1 file changed, 2 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index f71b9bc1e..8e6a6c08b 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -976,11 +976,9 @@ touch:
|
|
|
9ceacf |
/* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
|
|
9ceacf |
/* we skip the hard linked file containing the content */
|
|
|
9ceacf |
/* write the content to the first used instead */
|
|
|
9ceacf |
- char *fn = rpmfilesFN(files, firsthardlink);
|
|
|
9ceacf |
rc = rpmfiArchiveReadToFilePsm(fi, firstlinkfile, nodigest, psm);
|
|
|
9ceacf |
wfd_close(&firstlinkfile);
|
|
|
9ceacf |
firsthardlink = -1;
|
|
|
9ceacf |
- free(fn);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
if (rc) {
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From 9561315538f1fc4a5b207a43ac39805134e7153f Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Wed, 10 Feb 2021 09:57:17 +0200
|
|
|
9ceacf |
Subject: [PATCH 03/10] Don't update path info if rename failed on file commit
|
|
|
9ceacf |
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 16 +++++++++-------
|
|
|
9ceacf |
1 file changed, 9 insertions(+), 7 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index 8e6a6c08b..138b55297 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -797,14 +797,16 @@ static int fsmCommit(char **path, rpmfi fi, rpmFileAction action, const char *su
|
|
|
9ceacf |
/* Rename temporary to final file name if needed. */
|
|
|
9ceacf |
if (dest != *path) {
|
|
|
9ceacf |
rc = fsmRename(*path, dest);
|
|
|
9ceacf |
- if (!rc && nsuffix) {
|
|
|
9ceacf |
- char * opath = fsmFsPath(fi, NULL);
|
|
|
9ceacf |
- rpmlog(RPMLOG_WARNING, _("%s created as %s\n"),
|
|
|
9ceacf |
- opath, dest);
|
|
|
9ceacf |
- free(opath);
|
|
|
9ceacf |
+ if (!rc) {
|
|
|
9ceacf |
+ if (nsuffix) {
|
|
|
9ceacf |
+ char * opath = fsmFsPath(fi, NULL);
|
|
|
9ceacf |
+ rpmlog(RPMLOG_WARNING, _("%s created as %s\n"),
|
|
|
9ceacf |
+ opath, dest);
|
|
|
9ceacf |
+ free(opath);
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
+ free(*path);
|
|
|
9ceacf |
+ *path = dest;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- free(*path);
|
|
|
9ceacf |
- *path = dest;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From 73d090166a60c57484e4be40e46fcb07f026cbf8 Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Thu, 27 Aug 2020 10:31:07 +0300
|
|
|
9ceacf |
Subject: [PATCH 04/10] Upgrade FA_TOUCH to FA_CREATE if the file went away
|
|
|
9ceacf |
(RhBug:1872141)
|
|
|
9ceacf |
|
|
|
9ceacf |
When %_minimize_writes is enabled, we determine unchanged files during
|
|
|
9ceacf |
fingerprinting and only update their metadata (FA_TOUCH) instead of
|
|
|
9ceacf |
always recreating from scratch (FA_CREATE) during install. However
|
|
|
9ceacf |
package scriptlets (and administrators) can and will do arbitrary stuff
|
|
|
9ceacf |
in the meanwhile, such as rm -f their own files in %pre, hoping to
|
|
|
9ceacf |
get a fresh copy of contents no matter what. Or something.
|
|
|
9ceacf |
Now, if the file was determined to not need changing by rpm, this will
|
|
|
9ceacf |
just fail with chown & friends trying to touch non-existent file.
|
|
|
9ceacf |
One can consider this a case of package shooting itself in the foot, but
|
|
|
9ceacf |
when a package update fails or succeeds depending on %_minimize_writes this
|
|
|
9ceacf |
to me suggests the feature is at fault as much as the package.
|
|
|
9ceacf |
|
|
|
9ceacf |
Do fsmVerify() on all files to be FA_TOUCH'ed to detect files whose
|
|
|
9ceacf |
type changed or were removed since fingerprinting. This still doesn't
|
|
|
9ceacf |
ensure correctness if something tampers with the contents in the meanwhile,
|
|
|
9ceacf |
(for that we'd need to run the file through the whole machinery again,
|
|
|
9ceacf |
checksumming and all) but covers the most glaring cases.
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 15 ++++++---
|
|
|
9ceacf |
tests/Makefile.am | 1 +
|
|
|
9ceacf |
tests/data/SPECS/suicidal.spec | 19 ++++++++++++
|
|
|
9ceacf |
tests/rpmi.at | 56 ++++++++++++++++++++++++++++++++++
|
|
|
9ceacf |
4 files changed, 87 insertions(+), 4 deletions(-)
|
|
|
9ceacf |
create mode 100644 tests/data/SPECS/suicidal.spec
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index 138b55297..8a4ecaf05 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -920,10 +920,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
if (!skip) {
|
|
|
9ceacf |
int setmeta = 1;
|
|
|
9ceacf |
|
|
|
9ceacf |
- /* When touching we don't need any of this... */
|
|
|
9ceacf |
- if (action == FA_TOUCH)
|
|
|
9ceacf |
- goto touch;
|
|
|
9ceacf |
-
|
|
|
9ceacf |
/* Directories replacing something need early backup */
|
|
|
9ceacf |
if (!suffix) {
|
|
|
9ceacf |
rc = fsmBackup(fi, action);
|
|
|
9ceacf |
@@ -935,6 +931,17 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
rc = RPMERR_ENOENT;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
+ /* See if the file was removed while our attention was elsewhere */
|
|
|
9ceacf |
+ if (rc == RPMERR_ENOENT && action == FA_TOUCH) {
|
|
|
9ceacf |
+ rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n", fpath);
|
|
|
9ceacf |
+ action = FA_CREATE;
|
|
|
9ceacf |
+ fsmDebug(fpath, action, &sb);
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ /* When touching we don't need any of this... */
|
|
|
9ceacf |
+ if (action == FA_TOUCH)
|
|
|
9ceacf |
+ goto touch;
|
|
|
9ceacf |
+
|
|
|
9ceacf |
if (S_ISREG(sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
rc = fsmMkfile(fi, fpath, files, psm, nodigest,
|
|
|
9ceacf |
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
|
|
9ceacf |
index 7a6641d4f..d540e2a7b 100644
|
|
|
9ceacf |
--- a/tests/Makefile.am
|
|
|
9ceacf |
+++ b/tests/Makefile.am
|
|
|
9ceacf |
@@ -59,6 +59,7 @@ EXTRA_DIST += data/SPECS/verifyscript.spec
|
|
|
9ceacf |
EXTRA_DIST += data/SPECS/fakeshell.spec
|
|
|
9ceacf |
EXTRA_DIST += data/SPECS/scripts.spec
|
|
|
9ceacf |
EXTRA_DIST += data/SPECS/selfconflict.spec
|
|
|
9ceacf |
+EXTRA_DIST += data/SPECS/suicidal.spec
|
|
|
9ceacf |
EXTRA_DIST += data/SPECS/replacetest.spec
|
|
|
9ceacf |
EXTRA_DIST += data/SPECS/triggers.spec
|
|
|
9ceacf |
EXTRA_DIST += data/SPECS/filetriggers.spec
|
|
|
9ceacf |
diff --git a/tests/data/SPECS/suicidal.spec b/tests/data/SPECS/suicidal.spec
|
|
|
9ceacf |
new file mode 100644
|
|
|
9ceacf |
index 000000000..77d17d8c9
|
|
|
9ceacf |
--- /dev/null
|
|
|
9ceacf |
+++ b/tests/data/SPECS/suicidal.spec
|
|
|
9ceacf |
@@ -0,0 +1,19 @@
|
|
|
9ceacf |
+Name: suicidal
|
|
|
9ceacf |
+Version: 1
|
|
|
9ceacf |
+Release: %{rel}
|
|
|
9ceacf |
+License: GPL
|
|
|
9ceacf |
+Group: Testing
|
|
|
9ceacf |
+Summary: Testing suicidal package behavior
|
|
|
9ceacf |
+BuildArch: noarch
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+%description
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+%build
|
|
|
9ceacf |
+mkdir -p %{buildroot}/opt
|
|
|
9ceacf |
+echo shoot > %{buildroot}/opt/foot
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+%pre -p <lua>
|
|
|
9ceacf |
+os.remove('/opt/foot')
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+%files
|
|
|
9ceacf |
+/opt/foot
|
|
|
9ceacf |
diff --git a/tests/rpmi.at b/tests/rpmi.at
|
|
|
9ceacf |
index e8d6e9b7a..71e17821b 100644
|
|
|
9ceacf |
--- a/tests/rpmi.at
|
|
|
9ceacf |
+++ b/tests/rpmi.at
|
|
|
9ceacf |
@@ -711,3 +711,59 @@ runroot rpm -e testdoc
|
|
|
9ceacf |
[])
|
|
|
9ceacf |
AT_CLEANUP
|
|
|
9ceacf |
|
|
|
9ceacf |
+AT_SETUP([rpm -i --excludeartifacts])
|
|
|
9ceacf |
+AT_KEYWORDS([install])
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+runroot rpmbuild --quiet -bb /data/SPECS/vattrtest.spec
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+AT_CHECK([
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+runroot rpm -i --excludeartifacts /build/RPMS/noarch/vattrtest-1.0-1.noarch.rpm
|
|
|
9ceacf |
+test -e ${RPMTEST}/opt/vattrtest/a && exit 1
|
|
|
9ceacf |
+runroot rpm -e vattrtest
|
|
|
9ceacf |
+runroot rpm -i /build/RPMS/noarch/vattrtest-1.0-1.noarch.rpm
|
|
|
9ceacf |
+test -e ${RPMTEST}/opt/vattrtest/a || exit 1
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[0],
|
|
|
9ceacf |
+[],
|
|
|
9ceacf |
+[])
|
|
|
9ceacf |
+AT_CLEANUP
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+AT_SETUP([rpm -U <suicidal>])
|
|
|
9ceacf |
+AT_KEYWORDS([install])
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+for r in 1 2; do
|
|
|
9ceacf |
+ runroot rpmbuild -bb --quiet \
|
|
|
9ceacf |
+ --define "rel ${r}" \
|
|
|
9ceacf |
+ /data/SPECS/suicidal.spec
|
|
|
9ceacf |
+done
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+AT_CHECK([
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+for r in 1 2; do
|
|
|
9ceacf |
+ runroot rpm -U \
|
|
|
9ceacf |
+ --define "_minimize_writes 0" \
|
|
|
9ceacf |
+ /build/RPMS/noarch/suicidal-1-${r}.noarch.rpm
|
|
|
9ceacf |
+done
|
|
|
9ceacf |
+runroot rpm -V --nouser --nogroup suicidal
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[0],
|
|
|
9ceacf |
+[],
|
|
|
9ceacf |
+[])
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+AT_CHECK([
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+for r in 1 2; do
|
|
|
9ceacf |
+ runroot rpm -U \
|
|
|
9ceacf |
+ --define "_minimize_writes 1" \
|
|
|
9ceacf |
+ /build/RPMS/noarch/suicidal-1-${r}.noarch.rpm
|
|
|
9ceacf |
+done
|
|
|
9ceacf |
+runroot rpm -V --nouser --nogroup suicidal
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[0],
|
|
|
9ceacf |
+[],
|
|
|
9ceacf |
+[])
|
|
|
9ceacf |
+AT_CLEANUP
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From e78ea489eeed84cdee9f5cedcbbf35cfcf1a70b6 Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Wed, 10 Feb 2021 09:47:19 +0200
|
|
|
9ceacf |
Subject: [PATCH 05/10] Refactor file install and remove around a common struct
|
|
|
9ceacf |
|
|
|
9ceacf |
Collect the common state info into a struct shared by both file install
|
|
|
9ceacf |
and remove, update code accordingly. The change looks much more drastic
|
|
|
9ceacf |
than it is - it's just adding fp-> prefix to a lot of places.
|
|
|
9ceacf |
While we're at it, remember the state data throughout the operation.
|
|
|
9ceacf |
|
|
|
9ceacf |
No functional changes here, just paving way for the next steps which
|
|
|
9ceacf |
will look clearer with these pre-requisites in place.
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 158 +++++++++++++++++++++++++++++-------------------------
|
|
|
9ceacf |
1 file changed, 85 insertions(+), 73 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index 8a4ecaf05..ab15c2bf3 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -38,6 +38,14 @@ static int strict_erasures = 0;
|
|
|
9ceacf |
#define _dirPerms 0755
|
|
|
9ceacf |
#define _filePerms 0644
|
|
|
9ceacf |
|
|
|
9ceacf |
+struct filedata_s {
|
|
|
9ceacf |
+ int skip;
|
|
|
9ceacf |
+ rpmFileAction action;
|
|
|
9ceacf |
+ const char *suffix;
|
|
|
9ceacf |
+ char *fpath;
|
|
|
9ceacf |
+ struct stat sb;
|
|
|
9ceacf |
+};
|
|
|
9ceacf |
+
|
|
|
9ceacf |
/*
|
|
|
9ceacf |
* XXX Forward declarations for previously exported functions to avoid moving
|
|
|
9ceacf |
* things around needlessly
|
|
|
9ceacf |
@@ -864,19 +872,16 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
rpmfi fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
|
|
9ceacf |
rpmfs fs = rpmteGetFileStates(te);
|
|
|
9ceacf |
rpmPlugins plugins = rpmtsPlugins(ts);
|
|
|
9ceacf |
- struct stat sb;
|
|
|
9ceacf |
int saveerrno = errno;
|
|
|
9ceacf |
int rc = 0;
|
|
|
9ceacf |
int fx = -1;
|
|
|
9ceacf |
+ int fc = rpmfilesFC(files);
|
|
|
9ceacf |
int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0;
|
|
|
9ceacf |
int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0;
|
|
|
9ceacf |
int firsthardlink = -1;
|
|
|
9ceacf |
FD_t firstlinkfile = NULL;
|
|
|
9ceacf |
- int skip;
|
|
|
9ceacf |
- rpmFileAction action;
|
|
|
9ceacf |
char *tid = NULL;
|
|
|
9ceacf |
- const char *suffix;
|
|
|
9ceacf |
- char *fpath = NULL;
|
|
|
9ceacf |
+ struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
|
|
9ceacf |
|
|
|
9ceacf |
if (fi == NULL) {
|
|
|
9ceacf |
rc = RPMERR_BAD_MAGIC;
|
|
|
9ceacf |
@@ -890,96 +895,99 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
rc = fsmMkdirs(files, fs, plugins);
|
|
|
9ceacf |
|
|
|
9ceacf |
while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
|
|
9ceacf |
- action = rpmfsGetAction(fs, fx);
|
|
|
9ceacf |
- skip = XFA_SKIPPING(action);
|
|
|
9ceacf |
- if (action != FA_TOUCH) {
|
|
|
9ceacf |
- suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
|
|
9ceacf |
+ struct filedata_s *fp = &fdata[fx];
|
|
|
9ceacf |
+ fp->action = rpmfsGetAction(fs, fx);
|
|
|
9ceacf |
+ fp->skip = XFA_SKIPPING(fp->action);
|
|
|
9ceacf |
+ if (fp->action != FA_TOUCH) {
|
|
|
9ceacf |
+ fp->suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
- suffix = NULL;
|
|
|
9ceacf |
+ fp->suffix = NULL;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- fpath = fsmFsPath(fi, suffix);
|
|
|
9ceacf |
+ fp->fpath = fsmFsPath(fi, fp->suffix);
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Remap file perms, owner, and group. */
|
|
|
9ceacf |
- rc = rpmfiStat(fi, 1, &sb);
|
|
|
9ceacf |
+ rc = rpmfiStat(fi, 1, &fp->sb);
|
|
|
9ceacf |
|
|
|
9ceacf |
- fsmDebug(fpath, action, &sb);
|
|
|
9ceacf |
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Exit on error. */
|
|
|
9ceacf |
if (rc)
|
|
|
9ceacf |
break;
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Run fsm file pre hook for all plugins */
|
|
|
9ceacf |
- rc = rpmpluginsCallFsmFilePre(plugins, fi, fpath,
|
|
|
9ceacf |
- sb.st_mode, action);
|
|
|
9ceacf |
+ rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
|
|
|
9ceacf |
+ fp->sb.st_mode, fp->action);
|
|
|
9ceacf |
if (rc) {
|
|
|
9ceacf |
- skip = 1;
|
|
|
9ceacf |
+ fp->skip = 1;
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
setFileState(fs, fx);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (!skip) {
|
|
|
9ceacf |
+ if (!fp->skip) {
|
|
|
9ceacf |
int setmeta = 1;
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Directories replacing something need early backup */
|
|
|
9ceacf |
- if (!suffix) {
|
|
|
9ceacf |
- rc = fsmBackup(fi, action);
|
|
|
9ceacf |
+ if (!fp->suffix) {
|
|
|
9ceacf |
+ rc = fsmBackup(fi, fp->action);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
/* Assume file does't exist when tmp suffix is in use */
|
|
|
9ceacf |
- if (!suffix) {
|
|
|
9ceacf |
- rc = fsmVerify(fpath, fi);
|
|
|
9ceacf |
+ if (!fp->suffix) {
|
|
|
9ceacf |
+ rc = fsmVerify(fp->fpath, fi);
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
rc = RPMERR_ENOENT;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
/* See if the file was removed while our attention was elsewhere */
|
|
|
9ceacf |
- if (rc == RPMERR_ENOENT && action == FA_TOUCH) {
|
|
|
9ceacf |
- rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n", fpath);
|
|
|
9ceacf |
- action = FA_CREATE;
|
|
|
9ceacf |
- fsmDebug(fpath, action, &sb);
|
|
|
9ceacf |
+ if (rc == RPMERR_ENOENT && fp->action == FA_TOUCH) {
|
|
|
9ceacf |
+ rpmlog(RPMLOG_DEBUG, "file %s vanished unexpectedly\n",
|
|
|
9ceacf |
+ fp->fpath);
|
|
|
9ceacf |
+ fp->action = FA_CREATE;
|
|
|
9ceacf |
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
/* When touching we don't need any of this... */
|
|
|
9ceacf |
- if (action == FA_TOUCH)
|
|
|
9ceacf |
+ if (fp->action == FA_TOUCH)
|
|
|
9ceacf |
goto touch;
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (S_ISREG(sb.st_mode)) {
|
|
|
9ceacf |
+ if (S_ISREG(fp->sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
- rc = fsmMkfile(fi, fpath, files, psm, nodigest,
|
|
|
9ceacf |
+ rc = fsmMkfile(fi, fp->fpath, files, psm, nodigest,
|
|
|
9ceacf |
&setmeta, &firsthardlink, &firstlinkfile);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- } else if (S_ISDIR(sb.st_mode)) {
|
|
|
9ceacf |
+ } else if (S_ISDIR(fp->sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
- mode_t mode = sb.st_mode;
|
|
|
9ceacf |
+ mode_t mode = fp->sb.st_mode;
|
|
|
9ceacf |
mode &= ~07777;
|
|
|
9ceacf |
mode |= 00700;
|
|
|
9ceacf |
- rc = fsmMkdir(fpath, mode);
|
|
|
9ceacf |
+ rc = fsmMkdir(fp->fpath, mode);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- } else if (S_ISLNK(sb.st_mode)) {
|
|
|
9ceacf |
+ } else if (S_ISLNK(fp->sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
- rc = fsmSymlink(rpmfiFLink(fi), fpath);
|
|
|
9ceacf |
+ rc = fsmSymlink(rpmfiFLink(fi), fp->fpath);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- } else if (S_ISFIFO(sb.st_mode)) {
|
|
|
9ceacf |
+ } else if (S_ISFIFO(fp->sb.st_mode)) {
|
|
|
9ceacf |
/* This mimics cpio S_ISSOCK() behavior but probably isn't right */
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
- rc = fsmMkfifo(fpath, 0000);
|
|
|
9ceacf |
+ rc = fsmMkfifo(fp->fpath, 0000);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- } else if (S_ISCHR(sb.st_mode) ||
|
|
|
9ceacf |
- S_ISBLK(sb.st_mode) ||
|
|
|
9ceacf |
- S_ISSOCK(sb.st_mode))
|
|
|
9ceacf |
+ } else if (S_ISCHR(fp->sb.st_mode) ||
|
|
|
9ceacf |
+ S_ISBLK(fp->sb.st_mode) ||
|
|
|
9ceacf |
+ S_ISSOCK(fp->sb.st_mode))
|
|
|
9ceacf |
{
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
- rc = fsmMknod(fpath, sb.st_mode, sb.st_rdev);
|
|
|
9ceacf |
+ rc = fsmMknod(fp->fpath, fp->sb.st_mode, fp->sb.st_rdev);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
/* XXX Special case /dev/log, which shouldn't be packaged anyways */
|
|
|
9ceacf |
- if (!IS_DEV_LOG(fpath))
|
|
|
9ceacf |
+ if (!IS_DEV_LOG(fp->fpath))
|
|
|
9ceacf |
rc = RPMERR_UNKNOWN_FILETYPE;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
touch:
|
|
|
9ceacf |
/* Set permissions, timestamps etc for non-hardlink entries */
|
|
|
9ceacf |
if (!rc && setmeta) {
|
|
|
9ceacf |
- rc = fsmSetmeta(fpath, fi, plugins, action, &sb, nofcaps);
|
|
|
9ceacf |
+ rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
|
|
9ceacf |
+ &fp->sb, nofcaps);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
} else if (firsthardlink >= 0 && rpmfiArchiveHasContent(fi)) {
|
|
|
9ceacf |
/* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
|
|
9ceacf |
@@ -991,10 +999,10 @@ touch:
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
if (rc) {
|
|
|
9ceacf |
- if (!skip) {
|
|
|
9ceacf |
+ if (!fp->skip) {
|
|
|
9ceacf |
/* XXX only erase if temp fn w suffix is in use */
|
|
|
9ceacf |
- if (suffix) {
|
|
|
9ceacf |
- (void) fsmRemove(fpath, sb.st_mode);
|
|
|
9ceacf |
+ if (fp->suffix) {
|
|
|
9ceacf |
+ (void) fsmRemove(fp->fpath, fp->sb.st_mode);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
errno = saveerrno;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
@@ -1002,23 +1010,22 @@ touch:
|
|
|
9ceacf |
/* Notify on success. */
|
|
|
9ceacf |
rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, rpmfiArchiveTell(fi));
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (!skip) {
|
|
|
9ceacf |
+ if (!fp->skip) {
|
|
|
9ceacf |
/* Backup file if needed. Directories are handled earlier */
|
|
|
9ceacf |
- if (suffix)
|
|
|
9ceacf |
- rc = fsmBackup(fi, action);
|
|
|
9ceacf |
+ if (fp->suffix)
|
|
|
9ceacf |
+ rc = fsmBackup(fi, fp->action);
|
|
|
9ceacf |
|
|
|
9ceacf |
if (!rc)
|
|
|
9ceacf |
- rc = fsmCommit(&fpath, fi, action, suffix);
|
|
|
9ceacf |
+ rc = fsmCommit(&fp->fpath, fi, fp->action, fp->suffix);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
if (rc)
|
|
|
9ceacf |
- *failedFile = xstrdup(fpath);
|
|
|
9ceacf |
+ *failedFile = xstrdup(fp->fpath);
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Run fsm file post hook for all plugins */
|
|
|
9ceacf |
- rpmpluginsCallFsmFilePost(plugins, fi, fpath,
|
|
|
9ceacf |
- sb.st_mode, action, rc);
|
|
|
9ceacf |
- fpath = _free(fpath);
|
|
|
9ceacf |
+ rpmpluginsCallFsmFilePost(plugins, fi, fp->fpath,
|
|
|
9ceacf |
+ fp->sb.st_mode, fp->action, rc);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
if (!rc && fx != RPMERR_ITER_END)
|
|
|
9ceacf |
@@ -1034,7 +1041,9 @@ exit:
|
|
|
9ceacf |
rpmfiFree(fi);
|
|
|
9ceacf |
Fclose(payload);
|
|
|
9ceacf |
free(tid);
|
|
|
9ceacf |
- free(fpath);
|
|
|
9ceacf |
+ for (int i = 0; i < fc; i++)
|
|
|
9ceacf |
+ free(fdata[i].fpath);
|
|
|
9ceacf |
+ free(fdata);
|
|
|
9ceacf |
|
|
|
9ceacf |
return rc;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
@@ -1046,29 +1055,31 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
rpmfi fi = rpmfilesIter(files, RPMFI_ITER_BACK);
|
|
|
9ceacf |
rpmfs fs = rpmteGetFileStates(te);
|
|
|
9ceacf |
rpmPlugins plugins = rpmtsPlugins(ts);
|
|
|
9ceacf |
- struct stat sb;
|
|
|
9ceacf |
+ int fc = rpmfilesFC(files);
|
|
|
9ceacf |
+ int fx = -1;
|
|
|
9ceacf |
+ struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
|
|
9ceacf |
int rc = 0;
|
|
|
9ceacf |
- char *fpath = NULL;
|
|
|
9ceacf |
|
|
|
9ceacf |
- while (!rc && rpmfiNext(fi) >= 0) {
|
|
|
9ceacf |
- rpmFileAction action = rpmfsGetAction(fs, rpmfiFX(fi));
|
|
|
9ceacf |
- fpath = fsmFsPath(fi, NULL);
|
|
|
9ceacf |
- rc = fsmStat(fpath, 1, &sb);
|
|
|
9ceacf |
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
|
|
9ceacf |
+ struct filedata_s *fp = &fdata[fx];
|
|
|
9ceacf |
+ fp->action = rpmfsGetAction(fs, rpmfiFX(fi));
|
|
|
9ceacf |
+ fp->fpath = fsmFsPath(fi, NULL);
|
|
|
9ceacf |
+ rc = fsmStat(fp->fpath, 1, &fp->sb);
|
|
|
9ceacf |
|
|
|
9ceacf |
- fsmDebug(fpath, action, &sb);
|
|
|
9ceacf |
+ fsmDebug(fp->fpath, fp->action, &fp->sb);
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Run fsm file pre hook for all plugins */
|
|
|
9ceacf |
- rc = rpmpluginsCallFsmFilePre(plugins, fi, fpath,
|
|
|
9ceacf |
- sb.st_mode, action);
|
|
|
9ceacf |
+ rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
|
|
|
9ceacf |
+ fp->sb.st_mode, fp->action);
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (!XFA_SKIPPING(action))
|
|
|
9ceacf |
- rc = fsmBackup(fi, action);
|
|
|
9ceacf |
+ if (!XFA_SKIPPING(fp->action))
|
|
|
9ceacf |
+ rc = fsmBackup(fi, fp->action);
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Remove erased files. */
|
|
|
9ceacf |
- if (action == FA_ERASE) {
|
|
|
9ceacf |
+ if (fp->action == FA_ERASE) {
|
|
|
9ceacf |
int missingok = (rpmfiFFlags(fi) & (RPMFILE_MISSINGOK | RPMFILE_GHOST));
|
|
|
9ceacf |
|
|
|
9ceacf |
- rc = fsmRemove(fpath, sb.st_mode);
|
|
|
9ceacf |
+ rc = fsmRemove(fp->fpath, fp->sb.st_mode);
|
|
|
9ceacf |
|
|
|
9ceacf |
/*
|
|
|
9ceacf |
* Missing %ghost or %missingok entries are not errors.
|
|
|
9ceacf |
@@ -1093,20 +1104,20 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
if (rc) {
|
|
|
9ceacf |
int lvl = strict_erasures ? RPMLOG_ERR : RPMLOG_WARNING;
|
|
|
9ceacf |
rpmlog(lvl, _("%s %s: remove failed: %s\n"),
|
|
|
9ceacf |
- S_ISDIR(sb.st_mode) ? _("directory") : _("file"),
|
|
|
9ceacf |
- fpath, strerror(errno));
|
|
|
9ceacf |
+ S_ISDIR(fp->sb.st_mode) ? _("directory") : _("file"),
|
|
|
9ceacf |
+ fp->fpath, strerror(errno));
|
|
|
9ceacf |
}
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Run fsm file post hook for all plugins */
|
|
|
9ceacf |
- rpmpluginsCallFsmFilePost(plugins, fi, fpath,
|
|
|
9ceacf |
- sb.st_mode, action, rc);
|
|
|
9ceacf |
+ rpmpluginsCallFsmFilePost(plugins, fi, fp->fpath,
|
|
|
9ceacf |
+ fp->sb.st_mode, fp->action, rc);
|
|
|
9ceacf |
|
|
|
9ceacf |
/* XXX Failure to remove is not (yet) cause for failure. */
|
|
|
9ceacf |
if (!strict_erasures) rc = 0;
|
|
|
9ceacf |
|
|
|
9ceacf |
if (rc)
|
|
|
9ceacf |
- *failedFile = xstrdup(fpath);
|
|
|
9ceacf |
+ *failedFile = xstrdup(fp->fpath);
|
|
|
9ceacf |
|
|
|
9ceacf |
if (rc == 0) {
|
|
|
9ceacf |
/* Notify on success. */
|
|
|
9ceacf |
@@ -1114,10 +1125,11 @@ int rpmPackageFilesRemove(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
rpm_loff_t amount = rpmfiFC(fi) - rpmfiFX(fi);
|
|
|
9ceacf |
rpmpsmNotify(psm, RPMCALLBACK_UNINST_PROGRESS, amount);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- fpath = _free(fpath);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
- free(fpath);
|
|
|
9ceacf |
+ for (int i = 0; i < fc; i++)
|
|
|
9ceacf |
+ free(fdata[i].fpath);
|
|
|
9ceacf |
+ free(fdata);
|
|
|
9ceacf |
rpmfiFree(fi);
|
|
|
9ceacf |
|
|
|
9ceacf |
return rc;
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From 215525131b0e4e015d83c25828700d7531fec6dd Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Wed, 10 Feb 2021 10:08:27 +0200
|
|
|
9ceacf |
Subject: [PATCH 06/10] Refactor fsmMkfile() to take advantage of the new state
|
|
|
9ceacf |
struct
|
|
|
9ceacf |
|
|
|
9ceacf |
Move setmeta into the struct too (we'll want this later anyhow),
|
|
|
9ceacf |
and now we only need to pass the struct to fsmMkfile(). One less
|
|
|
9ceacf |
argument to pass around, it has way too many still.
|
|
|
9ceacf |
|
|
|
9ceacf |
No functional changes.
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 22 +++++++++++-----------
|
|
|
9ceacf |
1 file changed, 11 insertions(+), 11 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index ab15c2bf3..6c873206c 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -39,6 +39,7 @@ static int strict_erasures = 0;
|
|
|
9ceacf |
#define _filePerms 0644
|
|
|
9ceacf |
|
|
|
9ceacf |
struct filedata_s {
|
|
|
9ceacf |
+ int setmeta;
|
|
|
9ceacf |
int skip;
|
|
|
9ceacf |
rpmFileAction action;
|
|
|
9ceacf |
const char *suffix;
|
|
|
9ceacf |
@@ -279,8 +280,8 @@ exit:
|
|
|
9ceacf |
return rc;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
-static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
|
|
|
9ceacf |
- rpmpsm psm, int nodigest, int *setmeta,
|
|
|
9ceacf |
+static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
|
|
9ceacf |
+ rpmpsm psm, int nodigest,
|
|
|
9ceacf |
int * firsthardlink, FD_t *firstlinkfile)
|
|
|
9ceacf |
{
|
|
|
9ceacf |
int rc = 0;
|
|
|
9ceacf |
@@ -290,11 +291,11 @@ static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
|
|
|
9ceacf |
/* Create first hardlinked file empty */
|
|
|
9ceacf |
if (*firsthardlink < 0) {
|
|
|
9ceacf |
*firsthardlink = rpmfiFX(fi);
|
|
|
9ceacf |
- rc = wfd_open(firstlinkfile, dest);
|
|
|
9ceacf |
+ rc = wfd_open(firstlinkfile, fp->fpath);
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
/* Create hard links for others */
|
|
|
9ceacf |
char *fn = rpmfilesFN(files, *firsthardlink);
|
|
|
9ceacf |
- rc = link(fn, dest);
|
|
|
9ceacf |
+ rc = link(fn, fp->fpath);
|
|
|
9ceacf |
if (rc < 0) {
|
|
|
9ceacf |
rc = RPMERR_LINK_FAILED;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
@@ -305,14 +306,14 @@ static int fsmMkfile(rpmfi fi, const char *dest, rpmfiles files,
|
|
|
9ceacf |
existing) file with content */
|
|
|
9ceacf |
if (numHardlinks<=1) {
|
|
|
9ceacf |
if (!rc)
|
|
|
9ceacf |
- rc = expandRegular(fi, dest, psm, nodigest);
|
|
|
9ceacf |
+ rc = expandRegular(fi, fp->fpath, psm, nodigest);
|
|
|
9ceacf |
} else if (rpmfiArchiveHasContent(fi)) {
|
|
|
9ceacf |
if (!rc)
|
|
|
9ceacf |
rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm);
|
|
|
9ceacf |
wfd_close(firstlinkfile);
|
|
|
9ceacf |
*firsthardlink = -1;
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
- *setmeta = 0;
|
|
|
9ceacf |
+ fp->setmeta = 0;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
return rc;
|
|
|
9ceacf |
@@ -898,6 +899,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
struct filedata_s *fp = &fdata[fx];
|
|
|
9ceacf |
fp->action = rpmfsGetAction(fs, fx);
|
|
|
9ceacf |
fp->skip = XFA_SKIPPING(fp->action);
|
|
|
9ceacf |
+ fp->setmeta = 1;
|
|
|
9ceacf |
if (fp->action != FA_TOUCH) {
|
|
|
9ceacf |
fp->suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
@@ -924,8 +926,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
if (!fp->skip) {
|
|
|
9ceacf |
- int setmeta = 1;
|
|
|
9ceacf |
-
|
|
|
9ceacf |
/* Directories replacing something need early backup */
|
|
|
9ceacf |
if (!fp->suffix) {
|
|
|
9ceacf |
rc = fsmBackup(fi, fp->action);
|
|
|
9ceacf |
@@ -951,8 +951,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
|
|
|
9ceacf |
if (S_ISREG(fp->sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
- rc = fsmMkfile(fi, fp->fpath, files, psm, nodigest,
|
|
|
9ceacf |
- &setmeta, &firsthardlink, &firstlinkfile);
|
|
|
9ceacf |
+ rc = fsmMkfile(fi, fp, files, psm, nodigest,
|
|
|
9ceacf |
+ &firsthardlink, &firstlinkfile);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
} else if (S_ISDIR(fp->sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
@@ -985,7 +985,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
|
|
|
9ceacf |
touch:
|
|
|
9ceacf |
/* Set permissions, timestamps etc for non-hardlink entries */
|
|
|
9ceacf |
- if (!rc && setmeta) {
|
|
|
9ceacf |
+ if (!rc && fp->setmeta) {
|
|
|
9ceacf |
rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
|
|
9ceacf |
&fp->sb, nofcaps);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From 062167c2532a066301b15a0e85a1ac6cb6c07472 Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Wed, 10 Feb 2021 10:24:22 +0200
|
|
|
9ceacf |
Subject: [PATCH 07/10] Clarify file installation temporary suffix rule
|
|
|
9ceacf |
|
|
|
9ceacf |
We only use a temporary suffix for regular files that we are actually
|
|
|
9ceacf |
creating, skipped and touched files should not have it. Add XFA_CREATING()
|
|
|
9ceacf |
macro to accomppany XFA_SKIPPING() to easily check whether the file
|
|
|
9ceacf |
is being created or something else.
|
|
|
9ceacf |
|
|
|
9ceacf |
No functional changes but makes the logic clearer.
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 5 +----
|
|
|
9ceacf |
lib/rpmfiles.h | 3 +++
|
|
|
9ceacf |
2 files changed, 4 insertions(+), 4 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index 6c873206c..e4842a200 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -900,11 +900,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
fp->action = rpmfsGetAction(fs, fx);
|
|
|
9ceacf |
fp->skip = XFA_SKIPPING(fp->action);
|
|
|
9ceacf |
fp->setmeta = 1;
|
|
|
9ceacf |
- if (fp->action != FA_TOUCH) {
|
|
|
9ceacf |
+ if (XFA_CREATING(fp->action))
|
|
|
9ceacf |
fp->suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
|
|
9ceacf |
- } else {
|
|
|
9ceacf |
- fp->suffix = NULL;
|
|
|
9ceacf |
- }
|
|
|
9ceacf |
fp->fpath = fsmFsPath(fi, fp->suffix);
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Remap file perms, owner, and group. */
|
|
|
9ceacf |
diff --git a/lib/rpmfiles.h b/lib/rpmfiles.h
|
|
|
9ceacf |
index 64b33281a..7f3f82662 100644
|
|
|
9ceacf |
--- a/lib/rpmfiles.h
|
|
|
9ceacf |
+++ b/lib/rpmfiles.h
|
|
|
9ceacf |
@@ -90,6 +90,9 @@ typedef enum rpmFileAction_e {
|
|
|
9ceacf |
#define XFA_SKIPPING(_a) \
|
|
|
9ceacf |
((_a) == FA_SKIP || (_a) == FA_SKIPNSTATE || (_a) == FA_SKIPNETSHARED || (_a) == FA_SKIPCOLOR)
|
|
|
9ceacf |
|
|
|
9ceacf |
+#define XFA_CREATING(_a) \
|
|
|
9ceacf |
+ ((_a) == FA_CREATE || (_a) == FA_BACKUP || (_a) == FA_SAVE || (_a) == FA_ALTNAME)
|
|
|
9ceacf |
+
|
|
|
9ceacf |
/**
|
|
|
9ceacf |
* We pass these around as an array with a sentinel.
|
|
|
9ceacf |
*/
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From b3c6a3358dc4ec72fda0a229c22a5b79ac392848 Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Wed, 10 Feb 2021 10:24:22 +0200
|
|
|
9ceacf |
Subject: [PATCH 08/10] Clarify file installation temporary suffix rule
|
|
|
9ceacf |
|
|
|
9ceacf |
We only use a temporary suffix for regular files that we are actually
|
|
|
9ceacf |
creating, skipped and touched files should not have it. Add XFA_CREATING()
|
|
|
9ceacf |
macro to accomppany XFA_SKIPPING() to easily check whether the file
|
|
|
9ceacf |
is being created or something else.
|
|
|
9ceacf |
|
|
|
9ceacf |
No functional changes but makes the logic clearer.
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 4 ++--
|
|
|
9ceacf |
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index e4842a200..4d7c03895 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -900,8 +900,8 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
fp->action = rpmfsGetAction(fs, fx);
|
|
|
9ceacf |
fp->skip = XFA_SKIPPING(fp->action);
|
|
|
9ceacf |
fp->setmeta = 1;
|
|
|
9ceacf |
- if (XFA_CREATING(fp->action))
|
|
|
9ceacf |
- fp->suffix = S_ISDIR(rpmfiFMode(fi)) ? NULL : tid;
|
|
|
9ceacf |
+ if (XFA_CREATING(fp->action) && !S_ISDIR(rpmfiFMode(fi)))
|
|
|
9ceacf |
+ fp->suffix = tid;
|
|
|
9ceacf |
fp->fpath = fsmFsPath(fi, fp->suffix);
|
|
|
9ceacf |
|
|
|
9ceacf |
/* Remap file perms, owner, and group. */
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From 9097021b19c658ff55f7515878bae0592fd86377 Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Wed, 10 Feb 2021 11:25:10 +0200
|
|
|
9ceacf |
Subject: [PATCH 09/10] Handle hardlink tracking with a file state pointer
|
|
|
9ceacf |
|
|
|
9ceacf |
No functional changes, just makes it a little cleaner as firstlink now
|
|
|
9ceacf |
points to the actual file data instead of a index number somewhere.
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 20 +++++++++-----------
|
|
|
9ceacf |
1 file changed, 9 insertions(+), 11 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index 4d7c03895..cef17e669 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -282,24 +282,22 @@ exit:
|
|
|
9ceacf |
|
|
|
9ceacf |
static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
|
|
9ceacf |
rpmpsm psm, int nodigest,
|
|
|
9ceacf |
- int * firsthardlink, FD_t *firstlinkfile)
|
|
|
9ceacf |
+ struct filedata_s ** firstlink, FD_t *firstlinkfile)
|
|
|
9ceacf |
{
|
|
|
9ceacf |
int rc = 0;
|
|
|
9ceacf |
int numHardlinks = rpmfiFNlink(fi);
|
|
|
9ceacf |
|
|
|
9ceacf |
if (numHardlinks > 1) {
|
|
|
9ceacf |
/* Create first hardlinked file empty */
|
|
|
9ceacf |
- if (*firsthardlink < 0) {
|
|
|
9ceacf |
- *firsthardlink = rpmfiFX(fi);
|
|
|
9ceacf |
+ if (*firstlink == NULL) {
|
|
|
9ceacf |
+ *firstlink = fp;
|
|
|
9ceacf |
rc = wfd_open(firstlinkfile, fp->fpath);
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
/* Create hard links for others */
|
|
|
9ceacf |
- char *fn = rpmfilesFN(files, *firsthardlink);
|
|
|
9ceacf |
- rc = link(fn, fp->fpath);
|
|
|
9ceacf |
+ rc = link((*firstlink)->fpath, fp->fpath);
|
|
|
9ceacf |
if (rc < 0) {
|
|
|
9ceacf |
rc = RPMERR_LINK_FAILED;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- free(fn);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
}
|
|
|
9ceacf |
/* Write normal files or fill the last hardlinked (already
|
|
|
9ceacf |
@@ -311,7 +309,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
|
|
9ceacf |
if (!rc)
|
|
|
9ceacf |
rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm);
|
|
|
9ceacf |
wfd_close(firstlinkfile);
|
|
|
9ceacf |
- *firsthardlink = -1;
|
|
|
9ceacf |
+ *firstlink = NULL;
|
|
|
9ceacf |
} else {
|
|
|
9ceacf |
fp->setmeta = 0;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
@@ -879,10 +877,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
int fc = rpmfilesFC(files);
|
|
|
9ceacf |
int nodigest = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOFILEDIGEST) ? 1 : 0;
|
|
|
9ceacf |
int nofcaps = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCAPS) ? 1 : 0;
|
|
|
9ceacf |
- int firsthardlink = -1;
|
|
|
9ceacf |
FD_t firstlinkfile = NULL;
|
|
|
9ceacf |
char *tid = NULL;
|
|
|
9ceacf |
struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
|
|
9ceacf |
+ struct filedata_s *firstlink = NULL;
|
|
|
9ceacf |
|
|
|
9ceacf |
if (fi == NULL) {
|
|
|
9ceacf |
rc = RPMERR_BAD_MAGIC;
|
|
|
9ceacf |
@@ -949,7 +947,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
if (S_ISREG(fp->sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
rc = fsmMkfile(fi, fp, files, psm, nodigest,
|
|
|
9ceacf |
- &firsthardlink, &firstlinkfile);
|
|
|
9ceacf |
+ &firstlink, &firstlinkfile);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
} else if (S_ISDIR(fp->sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
@@ -986,13 +984,13 @@ touch:
|
|
|
9ceacf |
rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
|
|
9ceacf |
&fp->sb, nofcaps);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
- } else if (firsthardlink >= 0 && rpmfiArchiveHasContent(fi)) {
|
|
|
9ceacf |
+ } else if (firstlink && rpmfiArchiveHasContent(fi)) {
|
|
|
9ceacf |
/* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
|
|
9ceacf |
/* we skip the hard linked file containing the content */
|
|
|
9ceacf |
/* write the content to the first used instead */
|
|
|
9ceacf |
rc = rpmfiArchiveReadToFilePsm(fi, firstlinkfile, nodigest, psm);
|
|
|
9ceacf |
wfd_close(&firstlinkfile);
|
|
|
9ceacf |
- firsthardlink = -1;
|
|
|
9ceacf |
+ firstlink = NULL;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
if (rc) {
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|
|
|
9ceacf |
|
|
|
9ceacf |
From 357afe98316cb643a0757163ddbc276a071f1a18 Mon Sep 17 00:00:00 2001
|
|
|
9ceacf |
From: Panu Matilainen <pmatilai@redhat.com>
|
|
|
9ceacf |
Date: Wed, 10 Feb 2021 14:15:33 +0200
|
|
|
9ceacf |
Subject: [PATCH 10/10] Handle file install failures more gracefully
|
|
|
9ceacf |
|
|
|
9ceacf |
Run the file installation in multiple stages:
|
|
|
9ceacf |
1) gather intel
|
|
|
9ceacf |
2) unpack the archive to temporary files
|
|
|
9ceacf |
3) set file metadatas
|
|
|
9ceacf |
4) commit files to final location
|
|
|
9ceacf |
5) mop up leftovers on failure
|
|
|
9ceacf |
|
|
|
9ceacf |
This means we no longer leave behind a trail of untracked, potentially
|
|
|
9ceacf |
harmful junk on installation failure.
|
|
|
9ceacf |
|
|
|
9ceacf |
If commit step fails the package can still be left in an inconsistent stage,
|
|
|
9ceacf |
this could be further improved by first backing up old files to temporary
|
|
|
9ceacf |
location to allow undo on failure, but leaving that for some other day.
|
|
|
9ceacf |
Also unowned directories will still be left behind.
|
|
|
9ceacf |
|
|
|
9ceacf |
And yes, this is a somewhat scary change as it's the biggest ever change
|
|
|
9ceacf |
to how rpm lays down files on install. Adopt the hardlink test spec
|
|
|
9ceacf |
over to install tests and add some more tests for the new behavior.
|
|
|
9ceacf |
|
|
|
9ceacf |
Fixes: #967 (+ multiple reports over the years)
|
|
|
9ceacf |
---
|
|
|
9ceacf |
lib/fsm.c | 147 ++++++++++++++++++++------------
|
|
|
9ceacf |
tests/data/SPECS/hlinktest.spec | 4 +
|
|
|
9ceacf |
tests/rpmbuild.at | 33 -------
|
|
|
9ceacf |
tests/rpmi.at | 92 ++++++++++++++++++++
|
|
|
9ceacf |
4 files changed, 189 insertions(+), 87 deletions(-)
|
|
|
9ceacf |
|
|
|
9ceacf |
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
|
9ceacf |
index cef17e669..82af6f39f 100644
|
|
|
9ceacf |
--- a/lib/fsm.c
|
|
|
9ceacf |
+++ b/lib/fsm.c
|
|
|
9ceacf |
@@ -38,7 +38,17 @@ static int strict_erasures = 0;
|
|
|
9ceacf |
#define _dirPerms 0755
|
|
|
9ceacf |
#define _filePerms 0644
|
|
|
9ceacf |
|
|
|
9ceacf |
+enum filestage_e {
|
|
|
9ceacf |
+ FILE_COMMIT = -1,
|
|
|
9ceacf |
+ FILE_NONE = 0,
|
|
|
9ceacf |
+ FILE_PRE = 1,
|
|
|
9ceacf |
+ FILE_UNPACK = 2,
|
|
|
9ceacf |
+ FILE_PREP = 3,
|
|
|
9ceacf |
+ FILE_POST = 4,
|
|
|
9ceacf |
+};
|
|
|
9ceacf |
+
|
|
|
9ceacf |
struct filedata_s {
|
|
|
9ceacf |
+ int stage;
|
|
|
9ceacf |
int setmeta;
|
|
|
9ceacf |
int skip;
|
|
|
9ceacf |
rpmFileAction action;
|
|
|
9ceacf |
@@ -868,10 +878,9 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
rpmpsm psm, char ** failedFile)
|
|
|
9ceacf |
{
|
|
|
9ceacf |
FD_t payload = rpmtePayload(te);
|
|
|
9ceacf |
- rpmfi fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
|
|
9ceacf |
+ rpmfi fi = NULL;
|
|
|
9ceacf |
rpmfs fs = rpmteGetFileStates(te);
|
|
|
9ceacf |
rpmPlugins plugins = rpmtsPlugins(ts);
|
|
|
9ceacf |
- int saveerrno = errno;
|
|
|
9ceacf |
int rc = 0;
|
|
|
9ceacf |
int fx = -1;
|
|
|
9ceacf |
int fc = rpmfilesFC(files);
|
|
|
9ceacf |
@@ -882,20 +891,17 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
struct filedata_s *fdata = xcalloc(fc, sizeof(*fdata));
|
|
|
9ceacf |
struct filedata_s *firstlink = NULL;
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (fi == NULL) {
|
|
|
9ceacf |
- rc = RPMERR_BAD_MAGIC;
|
|
|
9ceacf |
- goto exit;
|
|
|
9ceacf |
- }
|
|
|
9ceacf |
-
|
|
|
9ceacf |
/* transaction id used for temporary path suffix while installing */
|
|
|
9ceacf |
rasprintf(&tid, ";%08x", (unsigned)rpmtsGetTid(ts));
|
|
|
9ceacf |
|
|
|
9ceacf |
- /* Detect and create directories not explicitly in package. */
|
|
|
9ceacf |
- rc = fsmMkdirs(files, fs, plugins);
|
|
|
9ceacf |
-
|
|
|
9ceacf |
+ /* Collect state data for the whole operation */
|
|
|
9ceacf |
+ fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
|
|
9ceacf |
while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
|
|
9ceacf |
struct filedata_s *fp = &fdata[fx];
|
|
|
9ceacf |
- fp->action = rpmfsGetAction(fs, fx);
|
|
|
9ceacf |
+ if (rpmfiFFlags(fi) & RPMFILE_GHOST)
|
|
|
9ceacf |
+ fp->action = FA_SKIP;
|
|
|
9ceacf |
+ else
|
|
|
9ceacf |
+ fp->action = rpmfsGetAction(fs, fx);
|
|
|
9ceacf |
fp->skip = XFA_SKIPPING(fp->action);
|
|
|
9ceacf |
fp->setmeta = 1;
|
|
|
9ceacf |
if (XFA_CREATING(fp->action) && !S_ISDIR(rpmfiFMode(fi)))
|
|
|
9ceacf |
@@ -905,20 +911,32 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
/* Remap file perms, owner, and group. */
|
|
|
9ceacf |
rc = rpmfiStat(fi, 1, &fp->sb);
|
|
|
9ceacf |
|
|
|
9ceacf |
+ setFileState(fs, fx);
|
|
|
9ceacf |
fsmDebug(fp->fpath, fp->action, &fp->sb);
|
|
|
9ceacf |
|
|
|
9ceacf |
- /* Exit on error. */
|
|
|
9ceacf |
- if (rc)
|
|
|
9ceacf |
- break;
|
|
|
9ceacf |
-
|
|
|
9ceacf |
/* Run fsm file pre hook for all plugins */
|
|
|
9ceacf |
rc = rpmpluginsCallFsmFilePre(plugins, fi, fp->fpath,
|
|
|
9ceacf |
fp->sb.st_mode, fp->action);
|
|
|
9ceacf |
- if (rc) {
|
|
|
9ceacf |
- fp->skip = 1;
|
|
|
9ceacf |
- } else {
|
|
|
9ceacf |
- setFileState(fs, fx);
|
|
|
9ceacf |
- }
|
|
|
9ceacf |
+ fp->stage = FILE_PRE;
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
+ fi = rpmfiFree(fi);
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ if (rc)
|
|
|
9ceacf |
+ goto exit;
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ fi = rpmfiNewArchiveReader(payload, files, RPMFI_ITER_READ_ARCHIVE);
|
|
|
9ceacf |
+ if (fi == NULL) {
|
|
|
9ceacf |
+ rc = RPMERR_BAD_MAGIC;
|
|
|
9ceacf |
+ goto exit;
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ /* Detect and create directories not explicitly in package. */
|
|
|
9ceacf |
+ if (!rc)
|
|
|
9ceacf |
+ rc = fsmMkdirs(files, fs, plugins);
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ /* Process the payload */
|
|
|
9ceacf |
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
|
|
9ceacf |
+ struct filedata_s *fp = &fdata[fx];
|
|
|
9ceacf |
|
|
|
9ceacf |
if (!fp->skip) {
|
|
|
9ceacf |
/* Directories replacing something need early backup */
|
|
|
9ceacf |
@@ -942,7 +960,7 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
|
|
|
9ceacf |
/* When touching we don't need any of this... */
|
|
|
9ceacf |
if (fp->action == FA_TOUCH)
|
|
|
9ceacf |
- goto touch;
|
|
|
9ceacf |
+ continue;
|
|
|
9ceacf |
|
|
|
9ceacf |
if (S_ISREG(fp->sb.st_mode)) {
|
|
|
9ceacf |
if (rc == RPMERR_ENOENT) {
|
|
|
9ceacf |
@@ -978,12 +996,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
|
9ceacf |
rc = RPMERR_UNKNOWN_FILETYPE;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
-touch:
|
|
|
9ceacf |
- /* Set permissions, timestamps etc for non-hardlink entries */
|
|
|
9ceacf |
- if (!rc && fp->setmeta) {
|
|
|
9ceacf |
- rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
|
|
9ceacf |
- &fp->sb, nofcaps);
|
|
|
9ceacf |
- }
|
|
|
9ceacf |
} else if (firstlink && rpmfiArchiveHasContent(fi)) {
|
|
|
9ceacf |
/* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
|
|
9ceacf |
/* we skip the hard linked file containing the content */
|
|
|
9ceacf |
@@ -993,47 +1005,74 @@ touch:
|
|
|
9ceacf |
firstlink = NULL;
|
|
|
9ceacf |
}
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (rc) {
|
|
|
9ceacf |
- if (!fp->skip) {
|
|
|
9ceacf |
- /* XXX only erase if temp fn w suffix is in use */
|
|
|
9ceacf |
- if (fp->suffix) {
|
|
|
9ceacf |
- (void) fsmRemove(fp->fpath, fp->sb.st_mode);
|
|
|
9ceacf |
- }
|
|
|
9ceacf |
- errno = saveerrno;
|
|
|
9ceacf |
- }
|
|
|
9ceacf |
- } else {
|
|
|
9ceacf |
- /* Notify on success. */
|
|
|
9ceacf |
+ /* Notify on success. */
|
|
|
9ceacf |
+ if (rc)
|
|
|
9ceacf |
+ *failedFile = xstrdup(fp->fpath);
|
|
|
9ceacf |
+ else
|
|
|
9ceacf |
rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, rpmfiArchiveTell(fi));
|
|
|
9ceacf |
+ fp->stage = FILE_UNPACK;
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
+ fi = rpmfiFree(fi);
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (!fp->skip) {
|
|
|
9ceacf |
- /* Backup file if needed. Directories are handled earlier */
|
|
|
9ceacf |
- if (fp->suffix)
|
|
|
9ceacf |
- rc = fsmBackup(fi, fp->action);
|
|
|
9ceacf |
+ if (!rc && fx < 0 && fx != RPMERR_ITER_END)
|
|
|
9ceacf |
+ rc = fx;
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (!rc)
|
|
|
9ceacf |
- rc = fsmCommit(&fp->fpath, fi, fp->action, fp->suffix);
|
|
|
9ceacf |
- }
|
|
|
9ceacf |
+ /* Set permissions, timestamps etc for non-hardlink entries */
|
|
|
9ceacf |
+ fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
|
|
9ceacf |
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
|
|
9ceacf |
+ struct filedata_s *fp = &fdata[fx];
|
|
|
9ceacf |
+ if (!fp->skip && fp->setmeta) {
|
|
|
9ceacf |
+ rc = fsmSetmeta(fp->fpath, fi, plugins, fp->action,
|
|
|
9ceacf |
+ &fp->sb, nofcaps);
|
|
|
9ceacf |
}
|
|
|
9ceacf |
-
|
|
|
9ceacf |
if (rc)
|
|
|
9ceacf |
*failedFile = xstrdup(fp->fpath);
|
|
|
9ceacf |
+ fp->stage = FILE_PREP;
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
+ fi = rpmfiFree(fi);
|
|
|
9ceacf |
|
|
|
9ceacf |
- /* Run fsm file post hook for all plugins */
|
|
|
9ceacf |
- rpmpluginsCallFsmFilePost(plugins, fi, fp->fpath,
|
|
|
9ceacf |
- fp->sb.st_mode, fp->action, rc);
|
|
|
9ceacf |
+ /* If all went well, commit files to final destination */
|
|
|
9ceacf |
+ fi = rpmfilesIter(files, RPMFI_ITER_FWD);
|
|
|
9ceacf |
+ while (!rc && (fx = rpmfiNext(fi)) >= 0) {
|
|
|
9ceacf |
+ struct filedata_s *fp = &fdata[fx];
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ if (!fp->skip) {
|
|
|
9ceacf |
+ /* Backup file if needed. Directories are handled earlier */
|
|
|
9ceacf |
+ if (!rc && fp->suffix)
|
|
|
9ceacf |
+ rc = fsmBackup(fi, fp->action);
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ if (!rc)
|
|
|
9ceacf |
+ rc = fsmCommit(&fp->fpath, fi, fp->action, fp->suffix);
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ if (!rc)
|
|
|
9ceacf |
+ fp->stage = FILE_COMMIT;
|
|
|
9ceacf |
+ else
|
|
|
9ceacf |
+ *failedFile = xstrdup(fp->fpath);
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
}
|
|
|
9ceacf |
+ fi = rpmfiFree(fi);
|
|
|
9ceacf |
|
|
|
9ceacf |
- if (!rc && fx != RPMERR_ITER_END)
|
|
|
9ceacf |
- rc = fx;
|
|
|
9ceacf |
+ /* Walk backwards in case we need to erase */
|
|
|
9ceacf |
+ fi = rpmfilesIter(files, RPMFI_ITER_BACK);
|
|
|
9ceacf |
+ while ((fx = rpmfiNext(fi)) >= 0) {
|
|
|
9ceacf |
+ struct filedata_s *fp = &fdata[fx];
|
|
|
9ceacf |
+ /* Run fsm file post hook for all plugins for all processed files */
|
|
|
9ceacf |
+ if (fp->stage) {
|
|
|
9ceacf |
+ rpmpluginsCallFsmFilePost(plugins, fi, fp->fpath,
|
|
|
9ceacf |
+ fp->sb.st_mode, fp->action, rc);
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+ /* On failure, erase non-committed files */
|
|
|
9ceacf |
+ if (rc && fp->stage > FILE_NONE && !fp->skip) {
|
|
|
9ceacf |
+ (void) fsmRemove(fp->fpath, fp->sb.st_mode);
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
+ }
|
|
|
9ceacf |
|
|
|
9ceacf |
rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS), fdOp(payload, FDSTAT_READ));
|
|
|
9ceacf |
rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST), fdOp(payload, FDSTAT_DIGEST));
|
|
|
9ceacf |
|
|
|
9ceacf |
exit:
|
|
|
9ceacf |
-
|
|
|
9ceacf |
- /* No need to bother with close errors on read */
|
|
|
9ceacf |
- rpmfiArchiveClose(fi);
|
|
|
9ceacf |
- rpmfiFree(fi);
|
|
|
9ceacf |
+ fi = rpmfiFree(fi);
|
|
|
9ceacf |
Fclose(payload);
|
|
|
9ceacf |
free(tid);
|
|
|
9ceacf |
for (int i = 0; i < fc; i++)
|
|
|
9ceacf |
diff --git a/tests/data/SPECS/hlinktest.spec b/tests/data/SPECS/hlinktest.spec
|
|
|
9ceacf |
index b3b8866fc..1f453524e 100644
|
|
|
9ceacf |
--- a/tests/data/SPECS/hlinktest.spec
|
|
|
9ceacf |
+++ b/tests/data/SPECS/hlinktest.spec
|
|
|
9ceacf |
@@ -1,5 +1,6 @@
|
|
|
9ceacf |
%bcond_with unpackaged_dirs
|
|
|
9ceacf |
%bcond_with unpackaged_files
|
|
|
9ceacf |
+%bcond_with owned_dir
|
|
|
9ceacf |
|
|
|
9ceacf |
Summary: Testing hard link behavior
|
|
|
9ceacf |
Name: hlinktest
|
|
|
9ceacf |
@@ -38,4 +39,7 @@ touch $RPM_BUILD_ROOT/toot
|
|
|
9ceacf |
|
|
|
9ceacf |
%files
|
|
|
9ceacf |
%defattr(-,root,root)
|
|
|
9ceacf |
+%if %{with owned_dir}
|
|
|
9ceacf |
+%dir /foo
|
|
|
9ceacf |
+%endif
|
|
|
9ceacf |
/foo/*
|
|
|
9ceacf |
diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at
|
|
|
9ceacf |
index 4294fd97c..c99fa7a63 100644
|
|
|
9ceacf |
--- a/tests/rpmbuild.at
|
|
|
9ceacf |
+++ b/tests/rpmbuild.at
|
|
|
9ceacf |
@@ -139,39 +139,6 @@ drwxrwxrwx zoot zoot /j/dir
|
|
|
9ceacf |
[])
|
|
|
9ceacf |
AT_CLEANUP
|
|
|
9ceacf |
|
|
|
9ceacf |
-# ------------------------------
|
|
|
9ceacf |
-# hardlink tests
|
|
|
9ceacf |
-AT_SETUP([rpmbuild hardlink])
|
|
|
9ceacf |
-AT_KEYWORDS([build])
|
|
|
9ceacf |
-AT_CHECK([
|
|
|
9ceacf |
-RPMDB_CLEAR
|
|
|
9ceacf |
-RPMDB_INIT
|
|
|
9ceacf |
-rm -rf ${TOPDIR}
|
|
|
9ceacf |
-
|
|
|
9ceacf |
-runroot rpmbuild \
|
|
|
9ceacf |
- -bb --quiet /data/SPECS/hlinktest.spec
|
|
|
9ceacf |
-
|
|
|
9ceacf |
-runroot rpm -i /build/RPMS/noarch/hlinktest-1.0-1.noarch.rpm
|
|
|
9ceacf |
-
|
|
|
9ceacf |
-runroot rpm -q --qf "[[%{filenlinks} %{filenames}\n]]%{longsize}\n" hlinktest
|
|
|
9ceacf |
-runroot rpm -V --nouser --nogroup hlinktest
|
|
|
9ceacf |
-ls -i "${RPMTEST}"/foo/hello* | awk {'print $1'} | sort -u | wc -l
|
|
|
9ceacf |
-
|
|
|
9ceacf |
-],
|
|
|
9ceacf |
-[0],
|
|
|
9ceacf |
-[2 /foo/aaaa
|
|
|
9ceacf |
-1 /foo/copyllo
|
|
|
9ceacf |
-4 /foo/hello
|
|
|
9ceacf |
-4 /foo/hello-bar
|
|
|
9ceacf |
-4 /foo/hello-foo
|
|
|
9ceacf |
-4 /foo/hello-world
|
|
|
9ceacf |
-2 /foo/zzzz
|
|
|
9ceacf |
-87
|
|
|
9ceacf |
-1
|
|
|
9ceacf |
-],
|
|
|
9ceacf |
-[])
|
|
|
9ceacf |
-AT_CLEANUP
|
|
|
9ceacf |
-
|
|
|
9ceacf |
AT_SETUP([rpmbuild unpackaged files])
|
|
|
9ceacf |
AT_KEYWORDS([build])
|
|
|
9ceacf |
AT_CHECK([
|
|
|
9ceacf |
diff --git a/tests/rpmi.at b/tests/rpmi.at
|
|
|
9ceacf |
index 71e17821b..bf1606b6d 100644
|
|
|
9ceacf |
--- a/tests/rpmi.at
|
|
|
9ceacf |
+++ b/tests/rpmi.at
|
|
|
9ceacf |
@@ -767,3 +767,95 @@ runroot rpm -V --nouser --nogroup suicidal
|
|
|
9ceacf |
[],
|
|
|
9ceacf |
[])
|
|
|
9ceacf |
AT_CLEANUP
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+# ------------------------------
|
|
|
9ceacf |
+# hardlink tests
|
|
|
9ceacf |
+AT_SETUP([rpm -i hardlinks])
|
|
|
9ceacf |
+AT_KEYWORDS([build install])
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+# Need a reproducable test package
|
|
|
9ceacf |
+runroot rpmbuild \
|
|
|
9ceacf |
+ --define "%optflags -O2 -g" \
|
|
|
9ceacf |
+ --define "%_target_platform noarch-linux" \
|
|
|
9ceacf |
+ --define "%_binary_payload w.ufdio" \
|
|
|
9ceacf |
+ --define "%_buildhost localhost" \
|
|
|
9ceacf |
+ --define "%use_source_date_epoch_as_buildtime 1" \
|
|
|
9ceacf |
+ --define "%source_date_epoch_from_changelog 1" \
|
|
|
9ceacf |
+ --define "%clamp_mtime_to_source_date_epoch 1" \
|
|
|
9ceacf |
+ --with owned_dir \
|
|
|
9ceacf |
+ -bb --quiet /data/SPECS/hlinktest.spec
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+pkg="/build/RPMS/noarch/hlinktest-1.0-1.noarch.rpm"
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+cp "${RPMTEST}/${pkg}" "${RPMTEST}/tmp/1.rpm"
|
|
|
9ceacf |
+dd if=/dev/zero of="${RPMTEST}/tmp/1.rpm" \
|
|
|
9ceacf |
+ conv=notrunc bs=1 seek=8180 count=6 2> /dev/null
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+cp "${RPMTEST}/${pkg}" "${RPMTEST}/tmp/2.rpm"
|
|
|
9ceacf |
+dd if=/dev/zero of="${RPMTEST}/tmp/2.rpm" \
|
|
|
9ceacf |
+ conv=notrunc bs=1 seek=8150 count=6 2> /dev/null
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+cp "${RPMTEST}/${pkg}" "${RPMTEST}/tmp/3.rpm"
|
|
|
9ceacf |
+dd if=/dev/zero of="${RPMTEST}/tmp/3.rpm" \
|
|
|
9ceacf |
+ conv=notrunc bs=1 seek=8050 count=6 2> /dev/null
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+AT_CHECK([
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+runroot rpm -i --noverify /tmp/1.rpm
|
|
|
9ceacf |
+# test that nothing of the contents remains after failure
|
|
|
9ceacf |
+test -d "${RPMTEST}/foo"
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[1],
|
|
|
9ceacf |
+[],
|
|
|
9ceacf |
+[error: unpacking of archive failed: cpio: Archive file not in header
|
|
|
9ceacf |
+error: hlinktest-1.0-1.noarch: install failed
|
|
|
9ceacf |
+])
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+AT_CHECK([
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+runroot rpm -i --noverify /tmp/2.rpm
|
|
|
9ceacf |
+# test that nothing of the contents remains after failure
|
|
|
9ceacf |
+test -d "${RPMTEST}/foo"
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[1],
|
|
|
9ceacf |
+[],
|
|
|
9ceacf |
+[error: unpacking of archive failed: cpio: Bad/unreadable header
|
|
|
9ceacf |
+error: hlinktest-1.0-1.noarch: install failed
|
|
|
9ceacf |
+])
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+AT_CHECK([
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+runroot rpm -i --noverify /tmp/3.rpm 2>&1| sed 's/;.*:/:/g'
|
|
|
9ceacf |
+# test that nothing of the contents remains after failure
|
|
|
9ceacf |
+test -d "${RPMTEST}/foo"
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[1],
|
|
|
9ceacf |
+[error: unpacking of archive failed on file /foo/hello-world: Digest mismatch
|
|
|
9ceacf |
+error: hlinktest-1.0-1.noarch: install failed
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[])
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+AT_CHECK([
|
|
|
9ceacf |
+RPMDB_INIT
|
|
|
9ceacf |
+runroot rpm -i /build/RPMS/noarch/hlinktest-1.0-1.noarch.rpm
|
|
|
9ceacf |
+runroot rpm -q --qf "[[%{filenlinks} %{filenames}\n]]%{longsize}\n" hlinktest
|
|
|
9ceacf |
+ls -i "${RPMTEST}"/foo/hello* | awk {'print $1'} | sort -u | wc -l
|
|
|
9ceacf |
+runroot rpm -e hlinktest
|
|
|
9ceacf |
+
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[0],
|
|
|
9ceacf |
+[1 /foo
|
|
|
9ceacf |
+2 /foo/aaaa
|
|
|
9ceacf |
+1 /foo/copyllo
|
|
|
9ceacf |
+4 /foo/hello
|
|
|
9ceacf |
+4 /foo/hello-bar
|
|
|
9ceacf |
+4 /foo/hello-foo
|
|
|
9ceacf |
+4 /foo/hello-world
|
|
|
9ceacf |
+2 /foo/zzzz
|
|
|
9ceacf |
+87
|
|
|
9ceacf |
+1
|
|
|
9ceacf |
+],
|
|
|
9ceacf |
+[])
|
|
|
9ceacf |
+AT_CLEANUP
|
|
|
9ceacf |
+
|
|
|
9ceacf |
--
|
|
|
9ceacf |
2.34.1
|
|
|
9ceacf |
|