Sanitize archive creation

- Get rid of the crazy tag-tango around rpmfi in genCpioListAndHeader():
  pkg->cpioList is an rpmfi with the actual in-package paths, and
  on-disk package paths are passed around as a separate array. This
  simplifies and sanitizes things a lot... and also finally gets rid
  of fi->apath entirely.
- Dependency generation wants on-disk paths, but it can generate those
  by prepending buildroot, which actually makes it more obvious what's
  going on.
- This also kills %{_noPayloadPrefix} ancient-history compatibility flag.
  We could honor it in rpmfiArchiveWriteHeader() if we cared but we're
  talking about rpm < 3.0.5 compatibility here ... so we dont.
This commit is contained in:
Panu Matilainen 2013-11-19 10:20:53 +02:00
parent e0dd56a156
commit 0c2a5d5868
7 changed files with 37 additions and 101 deletions

View File

@ -908,13 +908,9 @@ static int seenHardLink(FileRecords files, FileListRec flp, rpm_ino_t *fileid)
*/
static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
{
int _addDotSlash = !(isSrc || rpmExpandNumeric("%{_noPayloadPrefix}"));
size_t apathlen = 0;
size_t dpathlen = 0;
size_t skipLen = 0;
FileListRec flp;
char buf[BUFSIZ];
int i;
int i, npaths = 0;
uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo;
rpm_loff_t totalFileSize = 0;
Header h = pkg->header; /* just a shortcut */
@ -940,11 +936,9 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
qsort(fl->files.recs, fl->files.used,
sizeof(*(fl->files.recs)), compareFileListRecs);
/* Generate the header. */
if (! isSrc) {
skipLen = 1;
}
pkg->dpaths = xmalloc((fl->files.used + 1) * sizeof(*pkg->dpaths));
/* Generate the header. */
for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) {
rpm_ino_t fileid = flp - fl->files.recs;
@ -1002,19 +996,10 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
/* Skip files that were marked with %exclude. */
if (flp->flags & RPMFILE_EXCLUDE) continue;
/* Omit '/' and/or URL prefix, leave room for "./" prefix */
apathlen += (strlen(flp->cpioPath) - skipLen + (_addDotSlash ? 3 : 1));
/* Collect on-disk paths for archive creation */
pkg->dpaths[npaths++] = xstrdup(flp->diskPath);
/* Leave room for both dirname and basename NUL's */
dpathlen += (strlen(flp->diskPath) + 2);
/*
* Make the header. Store the on-disk path to OLDFILENAMES for
* cpio list generation purposes for now, final path temporarily
* to ORIGFILENAMES, to be swapped later into OLDFILENAMES.
*/
headerPutString(h, RPMTAG_OLDFILENAMES, flp->diskPath);
headerPutString(h, RPMTAG_ORIGFILENAMES, flp->cpioPath);
headerPutString(h, RPMTAG_OLDFILENAMES, flp->cpioPath);
headerPutString(h, RPMTAG_FILEUSERNAME,
rpmstrPoolStr(fl->pool, flp->uname));
headerPutString(h, RPMTAG_FILEGROUPNAME,
@ -1115,6 +1100,7 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
headerPutUint32(h, RPMTAG_FILEFLAGS, &(flp->flags) ,1);
}
pkg->dpaths[npaths] = NULL;
if (totalFileSize < UINT32_MAX) {
rpm_off_t totalsize = totalFileSize;
@ -1133,60 +1119,21 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
rpmlibNeedsFeature(pkg, "FileCaps", "4.6.1-1");
}
if (_addDotSlash)
(void) rpmlibNeedsFeature(pkg, "PayloadFilesHavePrefix", "4.0-1");
{
struct rpmtd_s filenames;
rpmfiFlags flags = RPMFI_NOHEADER|RPMFI_NOFILEUSER|RPMFI_NOFILEGROUP;
rpmfi fi;
int fc;
const char *fn;
char *a, **apath;
(void) rpmlibNeedsFeature(pkg, "PayloadFilesHavePrefix", "4.0-1");
/* rpmfiNew() only groks compressed filelists */
headerConvert(h, HEADERCONV_COMPRESSFILELIST);
fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, flags);
pkg->cpioList = rpmfiNew(NULL, h, RPMTAG_BASENAMES,
(RPMFI_NOFILEUSER|RPMFI_NOFILEGROUP));
if (fi == NULL) {
if (pkg->cpioList == NULL || rpmfiFC(pkg->cpioList) != npaths) {
fl->processingFailed = 1;
return;
}
/*
* Grab the real filenames from ORIGFILENAMES and put into OLDFILENAMES,
* remove temporary cruft and side-effects from filelist compression
* for rpmfiNew().
*/
headerGet(h, RPMTAG_ORIGFILENAMES, &filenames, HEADERGET_ALLOC);
headerDel(h, RPMTAG_ORIGFILENAMES);
headerDel(h, RPMTAG_BASENAMES);
headerDel(h, RPMTAG_DIRNAMES);
headerDel(h, RPMTAG_DIRINDEXES);
rpmtdSetTag(&filenames, RPMTAG_OLDFILENAMES);
headerPut(h, &filenames, HEADERPUT_DEFAULT);
/* Create hge-style archive path array, normally adding "./" */
fc = rpmtdCount(&filenames);
apath = xmalloc(fc * sizeof(*apath) + apathlen + 1);
a = (char *)(apath + fc);
*a = '\0';
rpmtdInit(&filenames);
for (int i = 0; (fn = rpmtdNextString(&filenames)); i++) {
apath[i] = a;
if (_addDotSlash)
a = stpcpy(a, "./");
a = stpcpy(a, (fn + skipLen));
a++; /* skip apath NUL */
}
rpmfiSetApath(fi, apath);
pkg->cpioList = fi;
rpmtdFreeData(&filenames);
}
/* Compress filelist unless legacy format requested */
if (!(fl->pkgFlags & RPMBUILD_PKG_NODIRTOKENS)) {
headerConvert(h, HEADERCONV_COMPRESSFILELIST);
if (fl->pkgFlags & RPMBUILD_PKG_NODIRTOKENS) {
/* Uncompress filelist if legacy format requested */
headerConvert(h, HEADERCONV_EXPANDFILELIST);
} else {
/* Binary packages with dirNames cannot be installed by legacy rpm. */
(void) rpmlibNeedsFeature(pkg, "CompressedFileNames", "3.0.4-1");
}

View File

@ -32,17 +32,19 @@
* @retval failedFile name of failed file on error
* @return 0 on success
*/
static int writeFile(rpmfi fi, int writeData, char **failedFile)
static int writeFile(rpmfi fi, ARGV_t dpaths, int writeData,
char **failedFile)
{
FD_t rfd = NULL;
int rc = 0;
const char *path = dpaths[rpmfiFX(fi)];
rc = rpmfiArchiveWriteHeader(fi);
if (rc) goto exit;
if (writeData && S_ISREG(rpmfiFMode(fi))) {
rfd = Fopen(rpmfiFN(fi), "r.ufdio");
rfd = Fopen(path, "r.ufdio");
if (Ferror(rfd)) {
rc = CPIOERR_OPEN_FAILED;
goto exit;
@ -61,7 +63,7 @@ static int writeFile(rpmfi fi, int writeData, char **failedFile)
exit:
if (rc && failedFile)
*failedFile = xstrdup(rpmfiFN(fi));
*failedFile = xstrdup(path);
if (rfd) {
/* preserve any prior errno across close */
int myerrno = errno;
@ -71,7 +73,7 @@ exit:
return rc;
}
static int writeLinks(rpmfi fi, char **failedFile)
static int writeLinks(rpmfi fi, ARGV_t dpaths, char **failedFile)
{
int rc = 0;
rpmfi xfi = rpmfilesIter(rpmfiFiles(fi), RPMFI_ITER_FWD);
@ -88,7 +90,7 @@ static int writeLinks(rpmfi fi, char **failedFile)
rpmfiSetFX(fi, hardlinks[j]);
/* Write data after last link. */
rc = writeFile(fi, (j == numHardlinks-1), failedFile);
rc = writeFile(fi, dpaths, (j == numHardlinks-1), failedFile);
if (rc)
break;
}
@ -100,7 +102,7 @@ static int writeLinks(rpmfi fi, char **failedFile)
return rc;
}
static int rpmPackageFilesArchive(rpmfi fi, int isSrc, FD_t cfd,
static int rpmPackageFilesArchive(rpmfi fi, int isSrc, FD_t cfd, ARGV_t dpaths,
rpm_loff_t * archiveSize, char ** failedFile)
{
int rc = rpmfiAttachArchive(fi, cfd, O_WRONLY);
@ -114,12 +116,12 @@ static int rpmPackageFilesArchive(rpmfi fi, int isSrc, FD_t cfd,
continue;
/* Copy file into archive. */
rc = writeFile(fi, 1, failedFile);
rc = writeFile(fi, dpaths, 1, failedFile);
}
/* Flush partial sets of hard linked files. */
if (!rc)
rc = writeLinks(fi, failedFile);
rc = writeLinks(fi, dpaths, failedFile);
if (archiveSize)
*archiveSize = (rc == 0) ? rpmfiArchiveTell(fi) : 0;
@ -145,7 +147,8 @@ static rpmRC cpio_doio(FD_t fdo, Package pkg, const char * fmodeMacro)
return RPMRC_FAIL;
fsmrc = rpmPackageFilesArchive(pkg->cpioList, headerIsSource(pkg->header),
cfd, &pkg->cpioArchiveSize, &failedFile);
cfd, pkg->dpaths,
&pkg->cpioArchiveSize, &failedFile);
if (fsmrc) {
char *emsg = rpmcpioStrerror(fsmrc);

View File

@ -99,6 +99,7 @@ struct Package_s {
rpmds order;
rpmfi cpioList;
rpm_loff_t cpioArchiveSize;
ARGV_t dpaths;
struct Source * icon;

View File

@ -1178,6 +1178,7 @@ static rpmRC rpmfcGenerateDependsHelper(const rpmSpec spec, Package pkg, rpmfi f
/* Create file manifest buffer to deliver to dependency finder. */
fi = rpmfiInit(fi, 0);
while (rpmfiNext(fi) >= 0)
appendStringBuf(sb_stdin, spec->buildRoot);
appendLineStringBuf(sb_stdin, rpmfiFN(fi));
for (DepMsg_t dm = DepMsgs; dm->msg != NULL; dm++) {
@ -1268,7 +1269,7 @@ rpmRC rpmfcGenerateDepends(const rpmSpec spec, Package pkg)
/* Does package have any %config files? */
genConfigDeps |= (rpmfiFFlags(fi) & RPMFILE_CONFIG);
av[idx] = xstrdup(rpmfiFN(fi));
av[idx] = rstrscat(NULL, spec->buildRoot, rpmfiFN(fi), NULL);
fmode[idx] = rpmfiFMode(fi);
}
av[ac] = NULL;

View File

@ -103,6 +103,7 @@ Package newPackage(const char *name, rpmstrPool pool, Package *pkglist)
p->fileFile = NULL;
p->policyList = NULL;
p->pool = rpmstrPoolLink(pool);
p->dpaths = NULL;
if (name)
p->name = rpmstrPoolId(p->pool, name, 1);
@ -145,6 +146,7 @@ static Package freePackage(Package pkg)
pkg->fileFile = argvFree(pkg->fileFile);
pkg->policyList = argvFree(pkg->policyList);
pkg->cpioList = rpmfiFree(pkg->cpioList);
pkg->dpaths = argvFree(pkg->dpaths);
pkg->icon = freeSources(pkg->icon);
pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);

View File

@ -50,7 +50,6 @@ struct rpmfi_s {
rpmfiles files; /*!< File info set */
rpmcpio_t archive; /*!< Archive with payload */
char ** apath;
int nrefs; /*!< Reference count */
};
@ -1136,7 +1135,6 @@ rpmfi rpmfiFree(rpmfi fi)
fi->files = rpmfilesFree(fi->files);
fi->fn = _free(fi->fn);
fi->ofn = _free(fi->ofn);
fi->apath = _free(fi->apath);
free(fi);
return NULL;
@ -1525,15 +1523,6 @@ void rpmfilesFpLookup(rpmfiles fi, fingerPrintCache fpc)
}
}
void rpmfiSetApath(rpmfi fi, char **apath)
{
if (fi != NULL) {
fi->apath = _free(fi->apath);
if (apath)
fi->apath = apath;
}
}
/*
* Generate iterator accessors function wrappers, these do nothing but
* call the corresponding rpmfiFooIndex(fi, fi->[ij])
@ -1706,15 +1695,11 @@ int rpmfiArchiveWriteHeader(rpmfi fi)
st.st_gid = gid;
st.st_size = fsize;
if (fi->apath) {
rc = rpmcpioHeaderWrite(fi->archive, fi->apath[rpmfiFX(fi)], &st);
} else {
const char * dn = rpmfiDN(fi);
char * path = rstrscat(NULL, (dn[0] == '/') ? "." : "",
dn, rpmfiBN(fi), NULL);
rc = rpmcpioHeaderWrite(fi->archive, path, &st);
free(path);
}
const char * dn = rpmfiDN(fi);
char * path = rstrscat(NULL, (dn[0] == '/') ? "." : "",
dn, rpmfiBN(fi), NULL);
rc = rpmcpioHeaderWrite(fi->archive, path, &st);
free(path);
}
return rc;

View File

@ -196,9 +196,6 @@ int rpmfilesDigestAlgo(rpmfiles fi);
rpm_color_t rpmfilesColor(rpmfiles files);
/* Temporary ugly kludge to eliminate direct struct rpmfi access... */
void rpmfiSetApath(rpmfi fi, char **apath);
/** \ingroup payload
* Add payload archive to the file info
* @param fi file info