From dce44771b2a3325b3dc1ebfe41027df9910a39fd Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Fri, 11 Feb 2022 13:18:11 +0200 Subject: [PATCH] Fix + sanitize the hardlink metadata setting logic Fix the initial setmeta value to something meaningful: we will never set metadata on skipped files, and hardlinks are handled with a special logic during install. They'd need different kind of special logic on FA_TOUCH so just play it safe and always apply metadata on those. Harlink metadata setting on install should happen on the *last* entry of hardlinked set that gets installed (wrt various skip scenarios) as otherwise creating those additional links affects the timestamp. Note in particular the "last file of..." case in fsmMkfile() where we the comment said just that, but set the metadata on the *first* file which would then be NULL'ed away. This all gets current masked by the fact that we do the metadata setting on a separate round, but that is about to change plus this makes the overall logic clearer anyhow. --- lib/fsm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/fsm.c b/lib/fsm.c index 82610c7..d9cfe6f 100644 --- a/lib/fsm.c +++ b/lib/fsm.c @@ -193,7 +193,6 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files, /* Create hard links for others and avoid redundant metadata setting */ if (*firstlink != fp) { rc = fsmLink((*firstlink)->fpath, fp->fpath); - fp->setmeta = 0; } fd = *firstlinkfile; } @@ -204,7 +203,7 @@ static int fsmMkfile(rpmfi fi, struct filedata_s *fp, rpmfiles files, rc = fsmUnpack(fi, fd, psm, nodigest); /* Last file of hardlink set, ensure metadata gets set */ if (*firstlink) { - (*firstlink)->setmeta = 1; + fp->setmeta = 1; *firstlink = NULL; *firstlinkfile = NULL; } @@ -797,7 +796,6 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, else fp->action = rpmfsGetAction(fs, fx); fp->skip = XFA_SKIPPING(fp->action); - fp->setmeta = 1; if (XFA_CREATING(fp->action) && !S_ISDIR(rpmfiFMode(fi))) fp->suffix = tid; fp->fpath = fsmFsPath(fi, fp->suffix); @@ -805,6 +803,10 @@ int rpmPackageFilesInstall(rpmts ts, rpmte te, rpmfiles files, /* Remap file perms, owner, and group. */ rc = rpmfiStat(fi, 1, &fp->sb); + /* Hardlinks are tricky and handled elsewhere for install */ + fp->setmeta = (fp->skip == 0) && + (fp->sb.st_nlink == 1 || fp->action == FA_TOUCH); + setFileState(fs, fx); fsmDebug(fp->fpath, fp->action, &fp->sb); -- 1.8.3.1