p->provideFlags = NULL;
}
- if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &p->files,
+ if (!headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &p->files,
&p->filesCount)) {
p->filesCount = 0;
p->files = NULL;
if (rc) goto exit;
}
- if (headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &files,
+ if (headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &files,
&fileCount)) {
rc = 0;
for (j = 0; j < fileCount; j++) {
#include "system.h"
#include <rpmlib.h>
+#include "misc.h"
static char * permsString(int mode)
{
uint_32 * usages;
int numFiles;
- if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &filenames, NULL))
+ if (!headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &filenames, NULL))
filenames = NULL;
if (!headerGetEntry(h, RPMTAG_FILESIZES, NULL, (void **) &filesizes,
return 0;
}
+static int filenamesTag(Header h, int_32 * type, /*@out@*/void ** data,
+ int_32 * count, int * freeData) {
+ *type = RPM_STRING_ARRAY_TYPE;
+
+ buildFileList(h, (char ***) data, count);
+ *freeData = 1;
+
+ *freeData = 0;
+
+ return 0;
+}
+
const struct headerSprintfExtension rpmHeaderFormats[] = {
+ { HEADER_EXT_TAG, "RPMTAG_FILENAMES", { filenamesTag } },
{ HEADER_EXT_TAG, "RPMTAG_FSSIZES", { fssizesTag } },
{ HEADER_EXT_TAG, "RPMTAG_FSNAMES", { fsnamesTag } },
{ HEADER_EXT_TAG, "RPMTAG_INSTALLPREFIX", { instprefixTag } },
*memPtr = mem;
- if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &mem->names,
+ if (!headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &mem->names,
fileCountPtr))
return 0;
if (!headerGetEntry(h, RPMTAG_ORIGFILENAMES, NULL,
(void **) &mem->cpioNames, NULL))
- headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &mem->cpioNames,
+ headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &mem->cpioNames,
fileCountPtr);
headerRemoveEntry(h, RPMTAG_ORIGFILENAMES);
}
rpmMessage(RPMMESS_DEBUG, _("spec file in: %s\n"), realSpecDir);
- if (h != NULL && headerIsEntry(h, RPMTAG_FILENAMES)) {
+ if (h != NULL && headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
/* we can't remap v1 packages */
assembleFileList(h, &fileMem, &fileCount, &files, 0, NULL);
/*@-unrecog@*/ chroot(rootdir); /*@=unrecog@*/
}
- if (!(flags & RPMTRANS_FLAG_JUSTDB) && headerIsEntry(h, RPMTAG_FILENAMES)) {
+ if (!(flags & RPMTRANS_FLAG_JUSTDB) && headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
const char * defaultPrefix;
/* old format relocateable packages need the entire default
prefix stripped to form the cpio list, while all other packages
if (fileMem) freeFileMemory(fileMem);
fileMem = NULL;
} else if (flags & RPMTRANS_FLAG_JUSTDB) {
- if (headerGetEntry(h, RPMTAG_FILENAMES, NULL, NULL, &fileCount)) {
+ if (headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, NULL, &fileCount)) {
fileStates = xmalloc(sizeof(*fileStates) * fileCount);
memset(fileStates, RPMFILE_STATE_NORMAL, fileCount);
headerAddEntry(h, RPMTAG_FILESTATES, RPM_CHAR_TYPE, fileStates,
return currDir;
}
+
+void compressFilelist(Header h) {
+ char ** files;
+ char ** dirList;
+ int * compDirList;
+ char ** baseNames;
+ int fileCount;
+ int i;
+ char * tail;
+ int lastDir = -1;
+
+ /* This assumes thie file list is already sorted, and begins with a
+ single '/'. That assumption isn't critical, but it makes things go
+ a bit faster. */
+
+ if (!headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &files,
+ &fileCount))
+ /* no file list */
+ return;
+
+ if (files[0][0] != '/') {
+ /* HACK. Source RPM, so just do things differently */
+ return ;
+ }
+
+ dirList = alloca(sizeof(*dirList) * fileCount); /* worst case */
+ baseNames = alloca(sizeof(*dirList) * fileCount);
+ compDirList = alloca(sizeof(*compDirList) * fileCount);
+
+ for (i = 0; i < fileCount; i++) {
+ tail = strrchr(files[i], '/') + 1;
+
+ if (lastDir < 0 ||
+ strncmp(dirList[lastDir], files[i], tail - files[i])) {
+ lastDir++;
+ dirList[lastDir] = alloca(tail - files[i] + 1);
+ memcpy(dirList[lastDir], files[i], tail - files[i]);
+ dirList[lastDir][tail - files[i]] = '\0';
+ }
+
+ compDirList[i] = lastDir;
+ baseNames[i] = tail;
+ }
+
+ headerAddEntry(h, RPMTAG_COMPDIRLIST, RPM_STRING_ARRAY_TYPE, dirList,
+ lastDir + 1);
+ headerAddEntry(h, RPMTAG_COMPFILEDIRS, RPM_INT32_TYPE, compDirList,
+ fileCount);
+ headerAddEntry(h, RPMTAG_COMPFILELIST, RPM_STRING_ARRAY_TYPE, baseNames,
+ fileCount);
+
+ free(files);
+
+ headerRemoveEntry(h, RPMTAG_OLDFILENAMES);
+}
+
+/* this is pretty straight-forward. The only thing that even resembles a trick
+ is getting all of this into a single malloc'd block */
+void buildFileList(Header h, char *** fileListPtr, int * fileCountPtr) {
+ int * dirList;
+ char ** dirs;
+ char ** tails;
+ int count;
+ char ** fileList;
+ int size;
+ char * data;
+ int i;
+
+ if (!headerGetEntry(h, RPMTAG_COMPFILELIST, NULL, (void **) &tails,
+ &count))
+ /* no file list */
+ return;
+
+ headerGetEntry(h, RPMTAG_COMPDIRLIST, NULL, (void **) &dirs,
+ &count);
+ headerGetEntry(h, RPMTAG_COMPFILEDIRS, NULL, (void **) &dirList,
+ &count);
+
+ size = sizeof(*fileList) * count;
+ for (i = 0; i < count; i++) {
+ size += strlen(tails[i]) + strlen(dirs[dirList[i]]) + 1;
+ }
+
+ fileList = malloc(size);
+ data = ((char *) fileList) + (sizeof(*fileList) * count);
+
+ for (i = 0; i < count; i++) {
+ fileList[i] = data;
+ strcpy(data, dirs[dirList[i]]);
+ strcat(data, tails[i]);
+ data += strlen(tails[i]) + strlen(dirs[dirList[i]]) + 1;
+ }
+
+ *fileListPtr = fileList;
+ *fileCountPtr = count;
+}
#include <unistd.h>
#include <sys/types.h>
+#include "header.h"
+
#ifdef __cplusplus
extern "C" {
#endif
int makeTempFile(const char * prefix, /*@out@*/ const char ** fnptr,
/*@out@*/ FD_t * fdptr);
char * currentDirectory(void); /* result needs to be freed */
+void compressFilelist(Header h);
+void buildFileList(Header h, char *** fileListPtr, int * fileCountPtr);
#ifdef __cplusplus
}
}
}
- headerAddEntry(*hdr, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE,
+ headerAddEntry(*hdr, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
fileList, spec.fileCount);
headerAddEntry(*hdr, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
fileLinktoList, spec.fileCount);
headerAddEntry(*hdr, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
gnames, spec.fileCount);
+ compressFilelist(*hdr);
+
free(fileList);
free(fileLinktoList);
free(fileMD5List);
&defaultPrefix, 1);
}
+ /* The file list was moved to a more compressed format which not
+ only saves memory (nice), but gives fingerprinting a nice, fat
+ speed boost (very nice). Go ahead and convert old headers to
+ the new style (this is a noop for new headers) */
+ compressFilelist(*hdr);
+
/* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
if (lead->type == RPMLEAD_SOURCE) {
if (!headerIsEntry(*hdr, RPMTAG_SOURCEPACKAGE))
const char * name, * version, * release;
int_32 count, type;
char * prefix = NULL;
- const char ** fileList;
+ const char ** dirList, ** baseNameList;
const char ** fileMD5List;
const char * fileStatesList;
const char ** fileOwnerList = NULL;
int_32 * fileGIDList = NULL;
uint_16 * fileModeList;
uint_16 * fileRdevList;
+ int_32 * dirIndexList;
int i;
headerNVR(h, &name, &version, &release);
queryHeader(fp, h, queryFormat);
if (queryFlags & QUERY_FOR_LIST) {
- if (!headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList,
- &count)) {
+ if (!headerGetEntry(h, RPMTAG_COMPFILELIST, &type,
+ (void **) &baseNameList, &count)) {
fputs(_("(contains no files)"), fp);
fputs("\n", fp);
} else {
(void **) &fileStatesList, &count)) {
fileStatesList = NULL;
}
+ headerGetEntry(h, RPMTAG_COMPDIRLIST, NULL,
+ (void **) &dirList, NULL);
+ headerGetEntry(h, RPMTAG_COMPFILEDIRS, NULL,
+ (void **) &dirIndexList, NULL);
headerGetEntry(h, RPMTAG_FILEFLAGS, &type,
(void **) &fileFlagsList, &count);
headerGetEntry(h, RPMTAG_FILESIZES, &type,
fputs( _("(no state) "), fp);
}
}
-
+
if (queryFlags & QUERY_FOR_DUMPFILES) {
- fprintf(fp, "%s %d %d %s 0%o ", fileList[i],
+ fprintf(fp, "%s%s %d %d %s 0%o ",
+ dirList[dirIndexList[i]], baseNameList[i],
fileSizeList[i], fileMTimeList[i],
fileMD5List[i], fileModeList[i]);
fprintf(fp, "X\n");
} else if (!rpmIsVerbose()) {
- fputs(fileList[i], fp);
+ fputs(dirList[dirIndexList[i]], fp);
+ fputs(baseNameList[i], fp);
fputs("\n", fp);
- } else if (fileOwnerList && fileGroupList)
- printFileInfo(fp, fileList[i], fileSizeList[i],
- fileModeList[i], fileMTimeList[i],
- fileRdevList[i], fileOwnerList[i],
- fileGroupList[i], -1,
- -1, fileLinktoList[i]);
- else if (fileUIDList && fileGIDList) {
- printFileInfo(fp, fileList[i], fileSizeList[i],
- fileModeList[i], fileMTimeList[i],
- fileRdevList[i], NULL,
- NULL, fileUIDList[i],
- fileGIDList[i], fileLinktoList[i]);
} else {
- rpmError(RPMERR_INTERNAL, _("package has "
- "neither file owner or id lists"));
+ char * filespec;
+
+ filespec = malloc(strlen(dirList[dirIndexList[i]])
+ + strlen(baseNameList[i]) + 1);
+ strcpy(filespec, dirList[dirIndexList[i]]);
+ strcat(filespec, baseNameList[i]);
+
+ if (fileOwnerList && fileGroupList) {
+ printFileInfo(fp, filespec, fileSizeList[i],
+ fileModeList[i], fileMTimeList[i],
+ fileRdevList[i],
+ fileOwnerList[i],
+ fileGroupList[i], -1,
+ -1, fileLinktoList[i]);
+ } else if (fileUIDList && fileGIDList) {
+ printFileInfo(fp, filespec, fileSizeList[i],
+ fileModeList[i], fileMTimeList[i],
+ fileRdevList[i], NULL,
+ NULL, fileUIDList[i],
+ fileGIDList[i],
+ fileLinktoList[i]);
+ } else {
+ rpmError(RPMERR_INTERNAL, _("package has "
+ "neither file owner or id lists"));
+ }
+
+ free(filespec);
}
}
}
- free(fileList);
+ free(dirList);
+ free(baseNameList);
free(fileLinktoList);
free(fileMD5List);
if (fileOwnerList) free(fileOwnerList);
if (pristine) return h;
- /* the RPM used to buildmuch of RH 5.1 could produce packages whose
+ /* the RPM used to build much of RH 5.1 could produce packages whose
file lists did not have leading /'s. Now is a good time to fix
that */
- if (!headerGetEntryMinMemory(h, RPMTAG_FILENAMES, NULL,
+ /* If this tag isn't present, either no files are in the package or
+ we're dealing with a package that has just the compressed file name
+ list */
+ if (!headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, NULL,
(void **) &fileList, &fileCount)) return h;
for (i = 0; i < fileCount; i++)
if (i == fileCount) {
free(fileList);
- return h;
- }
+ } else {
+ /* bad header -- let's clean it up */
+ newList = alloca(sizeof(*newList) * fileCount);
+ for (i = 0; i < fileCount; i++) {
+ newList[i] = alloca(strlen(fileList[i]) + 2);
+ if (*fileList[i] == '/')
+ strcpy(newList[i], fileList[i]);
+ else
+ sprintf(newList[i], "/%s", fileList[i]);
+ }
- /* bad header -- let's clean it up */
- newList = alloca(sizeof(*newList) * fileCount);
- for (i = 0; i < fileCount; i++) {
- newList[i] = alloca(strlen(fileList[i]) + 2);
- if (*fileList[i] == '/')
- strcpy(newList[i], fileList[i]);
- else
- sprintf(newList[i], "/%s", fileList[i]);
- }
+ free(fileList);
- free(fileList);
+ headerModifyEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
+ newList, fileCount);
+ }
- headerModifyEntry(h, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE,
- newList, fileCount);
+ /* The file list was moved to a more compressed format which not
+ only saves memory (nice), but gives fingerprinting a nice, fat
+ speed boost (very nice). Go ahead and convert old headers to
+ the new style (this is a noop for new headers) */
+ compressFilelist(h);
return h;
}
continue;
}
- headerGetEntryMinMemory(h, RPMTAG_FILENAMES, NULL,
+ headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, NULL,
(void **) &fileList, NULL);
do {
free(conflictList);
}
- if (headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList,
+ if (headerGetEntry(h, RPMTAG_OLDFILENAMES, &type, (void **) &fileList,
&count)) {
for (i = 0; i < count; i++) {
basename = strrchr(fileList[i], '/');
if (!group) group = "Unknown";
count = 0;
- headerGetEntry(dbentry, RPMTAG_FILENAMES, &type, (void **) &fileList,
+ headerGetEntry(dbentry, RPMTAG_OLDFILENAMES, &type, (void **) &fileList,
&count);
headerGetEntry(dbentry, RPMTAG_PROVIDENAME, &type, (void **) &providesList,
&providesCount);
{ const char ** fullfl, **fl;
int_32 fc;
- headerGetEntryMinMemory(h, RPMTAG_FILENAMES, NULL,
+ headerGetEntryMinMemory(h, RPMTAG_OLDFILENAMES, NULL,
(void **) &fullfl, &fc);
fl = xcalloc(num, sizeof(*fl));
#define RPMTAG_POSTIN 1024
#define RPMTAG_PREUN 1025
#define RPMTAG_POSTUN 1026
-#define RPMTAG_FILENAMES 1027
+#define RPMTAG_OLDFILENAMES 1027 /* obsolete */
#define RPMTAG_FILESIZES 1028
#define RPMTAG_FILESTATES 1029
#define RPMTAG_FILEMODES 1030
#define RPMTAG_PROVIDEVERSION 1113
#define RPMTAG_OBSOLETEFLAGS 1114
#define RPMTAG_OBSOLETEVERSION 1115
+#define RPMTAG_COMPFILEDIRS 1116
+#define RPMTAG_COMPFILELIST 1117
+#define RPMTAG_COMPDIRLIST 1118
-#define RPMTAG_FIRSTFREE_TAG 1116 /* internal */
+#define RPMTAG_FIRSTFREE_TAG 1119 /* internal */
#define RPMTAG_EXTERNAL_TAG 1000000
#define RPMFILE_STATE_NORMAL 0
xfree(validRelocations);
}
- headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &names, &fileCount);
+ headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &names, &fileCount);
/* Relocate all file paths.
* Go through sorted file and relocation lists backwards so that /usr/local
/* Save original filenames in header and replace (relocated) filenames. */
if (relocated) {
const char ** origNames;
- headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &origNames, NULL);
+ headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &origNames, NULL);
headerAddEntry(h, RPMTAG_ORIGFILENAMES, RPM_STRING_ARRAY_TYPE,
origNames, fileCount);
xfree(origNames);
- headerModifyEntry(h, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE,
+ headerModifyEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
names, fileCount);
}
dbiFreeIndexRecord(dbi);
}
- if (headerGetEntry(alp->h, RPMTAG_FILENAMES, NULL, NULL, &fileCount))
+ if (headerGetEntry(alp->h, RPMTAG_OLDFILENAMES, NULL, NULL, &fileCount))
totalFileCount += fileCount;
}
Header h;
if ((h = rpmdbGetRecord(ts->db, ts->removedPackages[i]))) {
- if (headerGetEntry(h, RPMTAG_FILENAMES, NULL, NULL,
+ if (headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, NULL,
&fileCount))
totalFileCount += fileCount;
headerFree(h);
i = ts->order[oc].u.addedIndex;
alp = ts->addedPackages.list + ts->order[oc].u.addedIndex;
- if (!headerGetEntryMinMemory(alp->h, RPMTAG_FILENAMES, NULL,
+ if (!headerGetEntryMinMemory(alp->h, RPMTAG_OLDFILENAMES, NULL,
NULL, &fi->fc)) {
fi->h = headerLink(alp->h);
hdrs[i] = headerLink(fi->h);
break;
}
- if (!headerGetEntry(fi->h, RPMTAG_FILENAMES, NULL,
+ if (!headerGetEntry(fi->h, RPMTAG_OLDFILENAMES, NULL,
(void **) &fi->fl, &fi->fc)) {
/* This catches removed packages w/ no file lists */
fi->fc = 0;
flags & RPMTRANS_FLAG_TEST);
if (!(flags & RPMTRANS_FLAG_JUSTDB) &&
- headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList,
+ headerGetEntry(h, RPMTAG_OLDFILENAMES, &type, (void **) &fileList,
&fileCount)) {
const char ** fileMd5List;
uint_32 * fileFlagsList;
int rpmVerifyFile(const char * prefix, Header h, int filenum, int * result,
int omitMask)
{
- char ** fileList, ** md5List, ** linktoList;
+ char ** baseNameList, ** md5List, ** linktoList, ** dirNameList;
int_32 * verifyFlags, flags;
- int_32 * sizeList, * mtimeList;
+ int_32 * sizeList, * mtimeList, * dirIndexList;
unsigned short * modeList, * rdevList;
char * fileStatesList;
char * filespec;
flags = RPMVERIFY_ALL;
}
- headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, &count);
- filespec = alloca(strlen(fileList[filenum]) + strlen(prefix) + 5);
- strcpy(filespec, prefix);
- strcat(filespec, "/");
- strcat(filespec, fileList[filenum]);
-
- free(fileList);
+ headerGetEntry(h, RPMTAG_COMPFILELIST, &type, (void **) &baseNameList,
+ &count);
+ headerGetEntry(h, RPMTAG_COMPFILEDIRS, &type, (void **) &dirIndexList,
+ NULL);
+ headerGetEntry(h, RPMTAG_COMPDIRLIST, &type, (void **) &dirNameList, NULL);
+
+ filespec = alloca(strlen(dirNameList[dirIndexList[filenum]]) +
+ strlen(baseNameList[filenum]) + strlen(prefix) + 5);
+ sprintf(filespec, "%s/%s%s", prefix, dirNameList[dirIndexList[filenum]],
+ baseNameList[filenum]);
+ free(baseNameList);
+ free(dirNameList);
*result = 0;
/* ======================================================================== */
static int verifyHeader(QVA_t *qva, Header h)
{
- const char ** fileList;
+ char ** fileList;
int count, type;
int verifyResult;
int i, ec, rc;
if (!(qva->qva_flags & VERIFY_MD5)) omitMask = RPMVERIFY_MD5;
if (headerGetEntry(h, RPMTAG_FILEFLAGS, NULL, (void **) &fileFlagsList, NULL) &&
- headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, &count)) {
+ headerIsEntry(h, RPMTAG_COMPFILELIST)) {
+ buildFileList(h, &fileList, &count);
+
for (i = 0; i < count; i++) {
if ((rc = rpmVerifyFile(qva->qva_prefix, h, i, &verifyResult, omitMask)) != 0) {
fprintf(stdout, _("missing %s\n"), fileList[i]);