From 670d639bfde427a4f3bb9a9f0350d581cacf6fdb Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Wed, 12 Aug 2020 18:23:42 +0200 Subject: [PATCH 04/13] Generate digest lists before calling genCpioListAndHeader() Signed-off-by: luhuaxin --- build/files.c | 182 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 147 insertions(+), 35 deletions(-) diff --git a/build/files.c b/build/files.c index dbac22f..84858b6 100644 --- a/build/files.c +++ b/build/files.c @@ -999,20 +999,149 @@ static int seenHardLink(FileRecords files, FileListRec flp, rpm_ino_t *fileid) * @param pkg (sub) package * @param isSrc pass 1 for source packages 0 otherwise */ -static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) +static void genDigestListInput(FileList fl, Package pkg, int isSrc) { FileListRec flp; char buf[BUFSIZ]; char file_info[BUFSIZ]; char file_digest[128 * 2 + 1]; + int i; + uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo; + Header h = pkg->header; /* just a shortcut */ + + /* + * See if non-md5 file digest algorithm is requested. If not + * specified, quietly assume md5. Otherwise check if supported type. + */ + digestalgo = rpmExpandNumeric(isSrc ? "%{_source_filedigest_algorithm}" : + "%{_binary_filedigest_algorithm}"); + if (digestalgo == 0) { + digestalgo = defaultalgo; + } + + if (rpmDigestLength(digestalgo) == 0) { + rpmlog(RPMLOG_WARNING, + _("Unknown file digest algorithm %u, falling back to MD5\n"), + digestalgo); + digestalgo = defaultalgo; + } + + /* Sort the big list */ + if (fl->files.recs) { + qsort(fl->files.recs, fl->files.used, + sizeof(*(fl->files.recs)), compareFileListRecs); + } + + /* Generate the header. */ + for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) { + /* Merge duplicate entries. */ + while (i < (fl->files.used - 1) && + rstreq(flp->cpioPath, flp[1].cpioPath)) { + + /* Two entries for the same file found, merge the entries. */ + /* Note that an %exclude is a duplication of a file reference */ + + /* file flags */ + flp[1].flags |= flp->flags; + + if (!(flp[1].flags & RPMFILE_EXCLUDE)) + rpmlog(RPMLOG_WARNING, _("File listed twice: %s\n"), + flp->cpioPath); + + /* file mode */ + if (S_ISDIR(flp->fl_mode)) { + if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) < + (flp->specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE))) + flp[1].fl_mode = flp->fl_mode; + } else { + if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) < + (flp->specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE))) + flp[1].fl_mode = flp->fl_mode; + } + + /* uid */ + if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) < + (flp->specdFlags & (SPECD_UID | SPECD_DEFUID))) + { + flp[1].fl_uid = flp->fl_uid; + flp[1].uname = flp->uname; + } + + /* gid */ + if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) < + (flp->specdFlags & (SPECD_GID | SPECD_DEFGID))) + { + flp[1].fl_gid = flp->fl_gid; + flp[1].gname = flp->gname; + } + + /* verify flags */ + if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) < + (flp->specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY))) + flp[1].verifyFlags = flp->verifyFlags; + + /* XXX to-do: language */ + + flp++; i++; + } + + /* Skip files that were marked with %exclude. */ + if (flp->flags & RPMFILE_EXCLUDE) + { + argvAdd(&pkg->fileExcludeList, flp->cpioPath); + continue; + } + + buf[0] = '\0'; + if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST)) + (void) rpmDoDigest(digestalgo, flp->diskPath, 1, + (unsigned char *)buf); + headerPutString(h, RPMTAG_FILEDIGESTS, buf); + snprintf(file_digest, sizeof(file_digest), "%s", buf); + + if (check_fileList_bin_pkg && S_ISREG(flp->fl_mode) && + !(flp->flags & RPMFILE_GHOST)) { + appendStringBuf(check_fileList_bin_pkg, "path="); + appendStringBuf(check_fileList_bin_pkg, flp->diskPath); + snprintf(file_info, sizeof(file_info), + "|digestalgopgp=%d|digest=%s|mode=%d" + "|uname=%s|gname=%s|caps=%s\n", + digestalgo, file_digest, flp->fl_mode, + rpmstrPoolStr(fl->pool, flp->uname), + rpmstrPoolStr(fl->pool, flp->gname), flp->caps && + strlen(flp->caps) ? flp->caps : ""); + appendStringBuf(check_fileList_bin_pkg, file_info); + } + } + + if (genDigestList(pkg->header, fl, check_fileList_bin_pkg) > 0) + fl->processingFailed = 1; +} + +/** + * Add file entries to header. + * @todo Should directories have %doc/%config attributes? (#14531) + * @todo Remove RPMTAG_OLDFILENAMES, add dirname/basename instead. + * @param fl package file tree walk data + * @param pkg (sub) package + * @param isSrc pass 1 for source packages 0 otherwise + */ +static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) +{ + FileListRec flp; + char buf[BUFSIZ]; int i, npaths = 0; int fail_on_dupes = rpmExpandNumeric("%{?_duplicate_files_terminate_build}") > 0; uint32_t defaultalgo = RPM_HASH_MD5, digestalgo; rpm_loff_t totalFileSize = 0; Header h = pkg->header; /* just a shortcut */ - int processed = 0; time_t source_date_epoch = 0; char *srcdate = getenv("SOURCE_DATE_EPOCH"); + struct rpmtd_s oldfiledigests; + + headerGet(h, RPMTAG_FILEDIGESTS, &oldfiledigests, HEADERGET_ALLOC); + headerDel(h, RPMTAG_FILEDIGESTS); + rpmtdInit(&oldfiledigests); /* Limit the maximum date to SOURCE_DATE_EPOCH if defined * similar to the tar --clamp-mtime option @@ -1079,9 +1208,8 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc) pkg->dpaths = xmalloc((fl->files.used + 1) * sizeof(*pkg->dpaths)); -process_files: /* Generate the header. */ - for (i = processed, flp = fl->files.recs + processed; i < fl->files.used; i++, flp++) { + for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) { rpm_ino_t fileid = flp - fl->files.recs; /* Merge duplicate entries. */ @@ -1211,13 +1339,17 @@ process_files: if (fl->haveCaps) { headerPutString(h, RPMTAG_FILECAPS, flp->caps); } - + buf[0] = '\0'; - if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST)) - (void) rpmDoDigest(digestalgo, flp->diskPath, 1, - (unsigned char *)buf); - headerPutString(h, RPMTAG_FILEDIGESTS, buf); - snprintf(file_digest, sizeof(file_digest), "%s", buf); + if (strstr(flp->diskPath, DIGEST_LIST_DIR) || !oldfiledigests.count) { + if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST)) + (void) rpmDoDigest(digestalgo, flp->diskPath, 1, + (unsigned char *)buf); + headerPutString(h, RPMTAG_FILEDIGESTS, buf); + } else { + headerPutString(h, RPMTAG_FILEDIGESTS, + rpmtdNextString(&oldfiledigests)); + } buf[0] = '\0'; if (S_ISLNK(flp->fl_mode)) { @@ -1258,31 +1390,6 @@ process_files: flp->flags &= PARSEATTR_MASK; headerPutUint32(h, RPMTAG_FILEFLAGS, &(flp->flags) ,1); - - if (!processed && check_fileList_bin_pkg && S_ISREG(flp->fl_mode) && - !(flp->flags & RPMFILE_GHOST)) { - appendStringBuf(check_fileList_bin_pkg, "path="); - appendStringBuf(check_fileList_bin_pkg, flp->diskPath); - snprintf(file_info, sizeof(file_info), - "|digestalgopgp=%d|digest=%s|mode=%d" - "|uname=%s|gname=%s|caps=%s\n", - digestalgo, file_digest, flp->fl_mode, - rpmstrPoolStr(fl->pool, flp->uname), - rpmstrPoolStr(fl->pool, flp->gname), flp->caps && - strlen(flp->caps) ? flp->caps : ""); - appendStringBuf(check_fileList_bin_pkg, file_info); - } - } - - if (!processed) { - if (genDigestList(pkg->header, fl, check_fileList_bin_pkg) > 0) { - fl->processingFailed = 1; - } else if (i < fl->files.used) { - pkg->dpaths = xrealloc(pkg->dpaths, - (fl->files.used + 1) * sizeof(*pkg->dpaths)); - processed = i; - goto process_files; - } } pkg->dpaths[npaths] = NULL; @@ -1323,6 +1430,7 @@ process_files: /* Binary packages with dirNames cannot be installed by legacy rpm. */ (void) rpmlibNeedsFeature(pkg, "CompressedFileNames", "3.0.4-1"); } + rpmtdFreeData(&oldfiledigests); } static FileRecords FileRecordsFree(FileRecords files) @@ -2805,6 +2913,10 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags, if (checkHardLinks(&fl.files)) (void) rpmlibNeedsFeature(pkg, "PartialHardlinkSets", "4.0.4-1"); + genDigestListInput(&fl, pkg, 0); + if (fl.processingFailed) + goto exit; + genCpioListAndHeader(&fl, pkg, 0); exit: -- 2.33.0