136 lines
4.2 KiB
Diff
136 lines
4.2 KiB
Diff
From 505699eb9789543a1b7bcaf8bb654d59b9d2623a Mon Sep 17 00:00:00 2001
|
|
From: Panu Matilainen <pmatilai@redhat.com>
|
|
Date: Thu, 11 Feb 2021 14:06:29 +0200
|
|
Subject: [PATCH] Streamline + consolidate the hardlink handling logic
|
|
|
|
Conflict:delete testcode
|
|
Reference:https://github.com/rpm-software-management/rpm/commit/505699eb9789543a1b7bcaf8bb654d59b9d2623a
|
|
|
|
This is one tricksy piece of code, in particular wrt interactions with
|
|
skipped files. Streamline the logic to make it easier to follow, and
|
|
consolidate as much as possible inside fsmMkfile() so there's only
|
|
one place opening, closing and writing to files. Add bunch of tests
|
|
for partially skipped sets.
|
|
|
|
This actually also fixes a case where metadata does not get properly
|
|
set on a partially skipped hardlink file set (the --excludepath=/foo/zzzz
|
|
case would fail prior to this)
|
|
---
|
|
lib/fsm.c | 80 ++++++++++++++++++++++-----------------------------
|
|
1 files changed, 35 insertions(+), 45 deletions(-)
|
|
|
|
diff --git a/lib/fsm.c b/lib/fsm.c
|
|
index ffafa5d68..bd2481a50 100644
|
|
--- a/lib/fsm.c
|
|
+++ b/lib/fsm.c
|
|
@@ -297,56 +297,45 @@ static int fsmOpen(FD_t *wfdp, const char *dest)
|
|
return rc;
|
|
}
|
|
|
|
-/** \ingroup payload
|
|
- * Create file from payload stream.
|
|
- * @return 0 on success
|
|
- */
|
|
-static int expandRegular(rpmfi fi, const char *dest, rpmpsm psm, int nodigest)
|
|
-{
|
|
- FD_t wfd = NULL;
|
|
- int rc;
|
|
-
|
|
- rc = fsmOpen(&wfd, dest);
|
|
- if (rc != 0)
|
|
- goto exit;
|
|
-
|
|
- rc = rpmfiArchiveReadToFilePsm(fi, wfd, nodigest, psm);
|
|
- fsmClose(&wfd);
|
|
-exit:
|
|
- return rc;
|
|
-}
|
|
-
|
|
static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files,
|
|
rpmpsm psm, int nodigest,
|
|
struct filedata_s ** firstlink, FD_t *firstlinkfile)
|
|
{
|
|
int rc = 0;
|
|
- int numHardlinks = rpmfiFNlink(fi);
|
|
+ FD_t fd = NULL;
|
|
|
|
- if (numHardlinks > 1) {
|
|
- /* Create first hardlinked file empty */
|
|
- if (*firstlink == NULL) {
|
|
+ if (*firstlink == NULL) {
|
|
+ /* First encounter, open file for writing */
|
|
+ rc = fsmOpen(&fd, fp->fpath);
|
|
+ /* If it's a part of a hardlinked set, the content may come later */
|
|
+ if (fp->sb.st_nlink > 1) {
|
|
*firstlink = fp;
|
|
- rc = fsmOpen(firstlinkfile, fp->fpath);
|
|
- } else {
|
|
- /* Create hard links for others */
|
|
+ *firstlinkfile = fd;
|
|
+ }
|
|
+ } else {
|
|
+ /* Create hard links for others and avoid redundant metadata setting */
|
|
+ if (*firstlink != fp) {
|
|
rc = fsmLink((*firstlink)->fpath, fp->fpath);
|
|
+ fp->setmeta = 0;
|
|
}
|
|
+ fd = *firstlinkfile;
|
|
}
|
|
- /* Write normal files or fill the last hardlinked (already
|
|
- existing) file with content */
|
|
- if (numHardlinks<=1) {
|
|
- if (!rc)
|
|
- rc = expandRegular(fi, fp->fpath, psm, nodigest);
|
|
- } else if (rpmfiArchiveHasContent(fi)) {
|
|
+
|
|
+ /* If the file has content, unpack it */
|
|
+ if (rpmfiArchiveHasContent(fi)) {
|
|
if (!rc)
|
|
- rc = rpmfiArchiveReadToFilePsm(fi, *firstlinkfile, nodigest, psm);
|
|
- fsmClose(firstlinkfile);
|
|
- *firstlink = NULL;
|
|
- } else {
|
|
- fp->setmeta = 0;
|
|
+ rc = rpmfiArchiveReadToFilePsm(fi, fd, nodigest, psm);
|
|
+ /* Last file of hardlink set, ensure metadata gets set */
|
|
+ if (*firstlink) {
|
|
+ (*firstlink)->setmeta = 1;
|
|
+ *firstlink = NULL;
|
|
+ *firstlinkfile = NULL;
|
|
+ }
|
|
}
|
|
|
|
+ if (fd != *firstlinkfile)
|
|
+ fsmClose(&fd);
|
|
+
|
|
return rc;
|
|
}
|
|
|
|
@@ -994,14 +983,15 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files,
|
|
if (!IS_DEV_LOG(fp->fpath))
|
|
rc = RPMERR_UNKNOWN_FILETYPE;
|
|
}
|
|
-
|
|
- } else if (firstlink && rpmfiArchiveHasContent(fi)) {
|
|
- /* On FA_TOUCH no hardlinks are created thus this is skipped. */
|
|
- /* we skip the hard linked file containing the content */
|
|
- /* write the content to the first used instead */
|
|
- rc = rpmfiArchiveReadToFilePsm(fi, firstlinkfile, nodigest, psm);
|
|
- fsmClose(&firstlinkfile);
|
|
- firstlink = NULL;
|
|
+ } else if (firstlink && rpmfiArchiveHasContent(fi)) {
|
|
+ /*
|
|
+ * Tricksy case: this file is a being skipped, but it's part of
|
|
+ * a hardlinked set and has the actual content linked with it.
|
|
+ * Write the content to the first non-skipped file of the set
|
|
+ * instead.
|
|
+ */
|
|
+ rc = fsmMkfile(fi, firstlink, files, psm, nodigest,
|
|
+ &firstlink, &firstlinkfile);
|
|
}
|
|
|
|
/* Notify on success. */
|
|
--
|
|
2.27.0
|
|
|