diff options
author | ewt <devnull@localhost> | 1999-10-08 20:30:49 +0000 |
---|---|---|
committer | ewt <devnull@localhost> | 1999-10-08 20:30:49 +0000 |
commit | cfa9ce427b7c5e2dbb9eba9fe94fff59833d53b3 (patch) | |
tree | 08ba2bd84c19d7c895dd4269ece4597c542457b6 /lib | |
parent | 568dceb42b2cdaaeafdcab97e155475ef6d1f2b2 (diff) | |
download | rpm-cfa9ce427b7c5e2dbb9eba9fe94fff59833d53b3.tar.gz rpm-cfa9ce427b7c5e2dbb9eba9fe94fff59833d53b3.tar.bz2 rpm-cfa9ce427b7c5e2dbb9eba9fe94fff59833d53b3.zip |
support new file list format for relocations and package removal
CVS patchset: 3379
CVS date: 1999/10/08 20:30:49
Diffstat (limited to 'lib')
-rw-r--r-- | lib/depends.c | 32 | ||||
-rw-r--r-- | lib/install.c | 2 | ||||
-rw-r--r-- | lib/rpmlib.h | 4 | ||||
-rw-r--r-- | lib/transaction.c | 224 | ||||
-rw-r--r-- | lib/uninstall.c | 44 |
5 files changed, 244 insertions, 62 deletions
diff --git a/lib/depends.c b/lib/depends.c index 7051bff7c..78ca0040b 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -1352,11 +1352,15 @@ int rpmdepCheck(rpmTransactionSet rpmdep, { struct availablePackage * p; int i, j; - const char ** files; + const char ** baseFileNames, ** dirList; + int_32 * dirIndexes; int fileCount; int rc; Header h = NULL; struct problemsSet ps; + char * filespec = NULL; + int fileAlloced = 0; + int len; ps.alloced = 5; ps.num = 0; @@ -1431,18 +1435,31 @@ int rpmdepCheck(rpmTransactionSet rpmdep, if (rc) goto exit; } - if (headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &files, - &fileCount)) { + if (headerGetEntry(h, RPMTAG_COMPFILELIST, NULL, + (void **) &baseFileNames, &fileCount)) { + headerGetEntry(h, RPMTAG_COMPDIRLIST, NULL, + (void **) &dirList, NULL); + headerGetEntry(h, RPMTAG_COMPFILEDIRS, NULL, + (void **) &dirIndexes, NULL); rc = 0; for (j = 0; j < fileCount; j++) { + len = strlen(baseFileNames[j]) + 1 + + strlen(dirList[dirIndexes[j]]); + if (len > fileAlloced) { + fileAlloced = len * 2; + filespec = xrealloc(filespec, fileAlloced); + } + strcpy(filespec, dirList[dirIndexes[j]]); + strcat(filespec, baseFileNames[j]); /* Erasing: check filename against requiredby matches. */ - if (checkDependentPackages(rpmdep, &ps, files[j])) { + if (checkDependentPackages(rpmdep, &ps, filespec)) { rc = 1; break; } } - free(files); + free(baseFileNames); + free(dirList); if (rc) goto exit; } @@ -1460,9 +1477,10 @@ int rpmdepCheck(rpmTransactionSet rpmdep, return 0; exit: - if (h) { + if (h) headerFree(h); - } + if (filespec) + free(filespec); if (ps.problems) free(ps.problems); return 1; } diff --git a/lib/install.c b/lib/install.c index a5549a7da..c451f5759 100644 --- a/lib/install.c +++ b/lib/install.c @@ -110,11 +110,13 @@ static int assembleFileList(Header h, /*@out@*/ struct fileMemory ** memPtr, fileCountPtr)) return 0; +#if 0 if (!headerGetEntry(h, RPMTAG_ORIGFILENAMES, NULL, (void **) &mem->cpioNames, NULL)) headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &mem->cpioNames, fileCountPtr); headerRemoveEntry(h, RPMTAG_ORIGFILENAMES); +#endif fileCount = *fileCountPtr; diff --git a/lib/rpmlib.h b/lib/rpmlib.h index 0f47d02cc..5d32536a4 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -137,7 +137,6 @@ extern const struct headerSprintfExtension rpmHeaderFormats[]; #define RPMTAG_AUTOPROV 1104 /* internal */ #define RPMTAG_CAPABILITY 1105 #define RPMTAG_SOURCEPACKAGE 1106 /* internal */ -#define RPMTAG_ORIGFILENAMES 1107 #define RPMTAG_BUILDPREREQ 1108 /* internal */ #define RPMTAG_BUILDREQUIRES 1109 /* internal */ #define RPMTAG_BUILDCONFLICTS 1110 /* internal */ @@ -149,6 +148,9 @@ extern const struct headerSprintfExtension rpmHeaderFormats[]; #define RPMTAG_COMPFILEDIRS 1116 #define RPMTAG_COMPFILELIST 1117 #define RPMTAG_COMPDIRLIST 1118 +#define RPMTAG_ORIGCOMPFILEDIRS 1119 /* internal */ +#define RPMTAG_ORIGCOMPFILELIST 1120 /* internal */ +#define RPMTAG_ORIGCOMPDIRLIST 1121 /* internal */ #define RPMTAG_FIRSTFREE_TAG 1119 /* internal */ #define RPMTAG_EXTERNAL_TAG 1000000 diff --git a/lib/transaction.c b/lib/transaction.c index 11a1dc95f..b94a5904d 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -246,9 +246,18 @@ static Header relocateFileList(struct availablePackage * alp, rpmRelocation * relocations = NULL; const char ** validRelocations; const char ** names; - int_32 fileCount; + char ** baseFileNames, ** dirNames; + int_32 * dirIndexes; + int_32 * newDirIndexes; + int_32 fileCount, dirCount; + char * skipDirList; Header h; - int relocated = 0; + int relocated = 0, len; + char * str; + int fileAlloced = 0; + char * filespec = NULL; + char * chptr; + int haveRelocatedFile = 0; if (!headerGetEntry(origH, RPMTAG_PREFIXES, NULL, (void **) &validRelocations, &numValid)) @@ -275,19 +284,19 @@ static Header relocateFileList(struct availablePackage * alp, /* FIXME: default relocations (oldPath == NULL) need to be handled in the UI, not rpmlib */ - { const char *s = rawRelocations[i].oldPath; - char *t = alloca(strlen(s) + 1); - strcpy(t, s); - stripTrailingSlashes(t); - relocations[i].oldPath = t; - } + /* FIXME: Trailing /'s will confuse us greatly. Internal ones will + too, but those are more trouble to fix up. :-( */ + str = alloca(strlen(rawRelocations[i].oldPath) + 1); + strcpy(str, rawRelocations[i].oldPath); + stripTrailingSlashes(str); + relocations[i].oldPath = str; + /* An old path w/o a new path is valid, and indicates exclusion */ if (rawRelocations[i].newPath) { - const char *s = rawRelocations[i].newPath; - char *t = alloca(strlen(s) + 1); - strcpy(t, s); - stripTrailingSlashes(t); - relocations[i].newPath = t; + str = alloca(strlen(rawRelocations[i].newPath) + 1); + strcpy(str, rawRelocations[i].newPath); + stripTrailingSlashes(str); + relocations[i].newPath = str; /* Verify that the relocation's old path is in the header. */ for (j = 0; j < numValid; j++) @@ -319,6 +328,7 @@ static Header relocateFileList(struct availablePackage * alp, /* Add relocation values to the header */ if (numValid) { const char ** actualRelocations; + actualRelocations = xmalloc(sizeof(*actualRelocations) * numValid); for (i = 0; i < numValid; i++) { for (j = 0; j < numRelocations; j++) { @@ -338,52 +348,185 @@ static Header relocateFileList(struct availablePackage * alp, xfree(validRelocations); } - headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &names, &fileCount); + /* For all relocations, we go through sorted file and relocation lists + * backwards so that /usr/local relocations take precedence over /usr + * ones. */ - /* Relocate all file paths. - * Go through sorted file and relocation lists backwards so that /usr/local - * relocations take precedence over /usr ones. - */ - for (i = fileCount - 1; i >= 0; i--) { + headerGetEntry(h, RPMTAG_COMPFILELIST, NULL, (void **) &baseFileNames, + &fileCount); + headerGetEntry(h, RPMTAG_COMPFILEDIRS, NULL, (void **) &dirIndexes, NULL); + headerGetEntry(h, RPMTAG_COMPDIRLIST, NULL, (void **) &dirNames, + &dirCount); + skipDirList = xcalloc(sizeof(*skipDirList), dirCount); + + newDirIndexes = alloca(sizeof(*newDirIndexes) * fileCount); + memcpy(newDirIndexes, dirIndex, sizeof(*newDirIndexes) * fileCount); + dirIndexes = newDirIndexes; + + /* Start off by relocating directories. */ + for (i = dirCount - 1; i >= 0; i--) { for (j = numRelocations - 1; j >= 0; j--) { int len; + len = strlen(relocations[j].oldPath); - if (strncmp(relocations[j].oldPath, names[i], len)) + if (strncmp(relocations[j].oldPath, dirNames[i], len)) continue; - /* Only directories or complete file paths can be relocated */ - if (!(names[i][len] == '/' || names[i][len] == '\0')) + /* Only subdirectories or complete file paths may be relocated. We + don't check for '\0' as our directory names all end in '/'. */ + if (!(dirNames[i][len] == '/')) continue; if (relocations[j].newPath) { /* Relocate the path */ const char *s = relocations[j].newPath; - char *t = alloca(strlen(s) + strlen(names[i]) - len + 1); + char *t = alloca(strlen(s) + strlen(dirNames[i]) - len + 1); + strcpy(t, s); - strcat(t, names[i] + len); - rpmMessage(RPMMESS_DEBUG, _("relocating %s to %s\n"), - names[i], t); - names[i] = t; + strcat(t, dirNames[i] + len); + rpmMessage(RPMMESS_DEBUG, _("relocating directory %s to %s\n"), + dirNames[i], t); + dirNames[i] = t; relocated = 1; - } else /* On install, a relocate to NULL means skip the file */ - if (actions) { - actions[i] = FA_SKIPNSTATE; - rpmMessage(RPMMESS_DEBUG, _("excluding %s\n"), names[i]); + } else if (actions) { + /* On install, a relocate to NULL means skip the file */ + skipDirList[i] = 1; + rpmMessage(RPMMESS_DEBUG, _("excluding directory %s\n"), + dirNames[i]); } break; } } + /* Now relocate individual files. */ + + for (i = fileCount - 1; i >= 0; i--) { + /* If we're skipping the directory this file is part of, skip this + file as well. */ + if (skipDirList[dirIndexes[i]]) { + actions[i] = FA_SKIPNSTATE; + rpmMessage(RPMMESS_DEBUG, _("excluding file %s%s\n"), + dirNames[dirIndexes[i]], baseFileNames[i]); + continue; + } + + /* See if this file needs relocating (which will only occur if the + full file path we have exactly matches a path in the relocation + list. XXX FIXME: Would a bsearch of the (already sorted) + relocation list be a good idea? */ + + len = strlen(dirNames[dirIndexes[i]]) + strlen(baseFileNames[i]) + 1; + if (len >= fileAlloced) { + fileAlloced = len * 2; + filespec = xrealloc(filespec, fileAlloced); + } + strcpy(filespec, dirNames[dirIndexes[i]]); + strcat(filespec, baseFileNames[i]); + + for (j = numRelocations - 1; j >= 0; j--) + if (!strcmp(relocations[j].oldPath, filespec)) break; + + if (j < 0) continue; + + if (actions && !relocations[j].newPath) { + /* On install, a relocate to NULL means skip the file */ + skipDirList[i] = 1; + rpmMessage(RPMMESS_DEBUG, _("excluding directory %s\n"), + dirNames[i]); + continue; + } + + rpmMessage(RPMMESS_DEBUG, _("relocating %s to %s\n"), + filespec, relocations[j].newPath); + relocated = 1; + + len = strlen(relocations[j].newPath); + if (len >= fileAlloced) { + fileAlloced = len * 2; + filespec = xrealloc(filespec, fileAlloced); + } + strcpy(filespec, relocations[j].newPath); + chptr = strrchr(filespec, '/'); + *chptr++ = '\0'; + + /* filespec is the new path, and chptr is the new basename */ + if (strcmp(baseFileNames[i], chptr)) { + baseFileNames[i] = alloca(strlen(chptr) + 1); + strcpy(baseFileNames[i], chptr); + } + + /* Does this directory already exist in the directory list? */ + for (j = 0; j < dirCount; j++) + if (!strcmp(filespec, dirNames[j])) break; + + if (j < dirCount) { + dirIndexes[i] = j; + continue; + } + + /* Creating new paths is a pita */ + if (!haveRelocatedFile) { + char ** newDirList; + int k; + + haveRelocatedFile = 1; + newDirList = malloc(sizeof(*newDirList) * (dirCount + 1)); + for (k = 0; k < dirCount; k++) { + newDirList[k] = alloca(strlen(dirNames[k]) + 1); + strcpy(newDirList[k], dirNames[k]); + } + free(dirNames); + dirNames = newDirList; + } else { + dirNames = realloc(dirNames, + sizeof(*dirNames) * (dirCount + 1)); + } + + dirNames[dirCount] = alloca(strlen(filespec) + 1); + strcpy(dirNames[dirCount], filespec); + dirIndexes[i] = dirCount; + dirCount++; + } + +/*XXX FIXME: this needs to be updated to deal with compressed lists! will + be straightforward */ + /* Save original filenames in header and replace (relocated) filenames. */ if (relocated) { const char ** origNames; - headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, (void **) &origNames, NULL); - headerAddEntry(h, RPMTAG_ORIGFILENAMES, RPM_STRING_ARRAY_TYPE, + int origDirCount; + int_32 * origDirIndexes; + + headerGetEntry(h, RPMTAG_COMPFILELIST, NULL, (void **) &origNames, + NULL); + headerAddEntry(h, RPMTAG_ORIGCOMPFILELIST, RPM_STRING_ARRAY_TYPE, origNames, fileCount); xfree(origNames); - headerModifyEntry(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE, - names, fileCount); + + headerGetEntry(h, RPMTAG_COMPDIRLIST, NULL, (void **) &origNames, + &origDirCount); + headerAddEntry(h, RPMTAG_ORIGCOMPDIRLIST, RPM_STRING_ARRAY_TYPE, + origNames, origDirCount); + xfree(origNames); + + headerGetEntry(h, RPMTAG_COMPFILEDIRS, NULL, (void **) &origDirIndexes, + NULL); + headerAddEntry(h, RPMTAG_ORIGCOMPDIRLIST, RPM_STRING_ARRAY_TYPE, + origDirIndexes, fileCount); + xfree(origNames); + + headerModifyEntry(h, RPMTAG_COMPFILELIST, RPM_STRING_ARRAY_TYPE, + baseFileNames, fileCount); + headerModifyEntry(h, RPMTAG_COMPFILEDIRS, RPM_STRING_ARRAY_TYPE, + dirIndexes, fileCount); + headerModifyEntry(h, RPMTAG_COMPDIRLIST, RPM_STRING_ARRAY_TYPE, + dirNames, dirCount); } + free(baseFileNames); + free(dirNames); + if (filespec) free(filespec); + free(skipDirList); + xfree(names); return h; @@ -1115,7 +1258,8 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, dbiFreeIndexRecord(dbi); } - if (headerGetEntry(alp->h, RPMTAG_OLDFILENAMES, NULL, NULL, &fileCount)) + if (headerGetEntry(alp->h, RPMTAG_COMPFILELIST, NULL, NULL, + &fileCount)) totalFileCount += fileCount; } @@ -1125,7 +1269,7 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, Header h; if ((h = rpmdbGetRecord(ts->db, ts->removedPackages[i]))) { - if (headerGetEntry(h, RPMTAG_OLDFILENAMES, NULL, NULL, + if (headerGetEntry(h, RPMTAG_COMPFILELIST, NULL, NULL, &fileCount)) totalFileCount += fileCount; headerFree(h); @@ -1138,8 +1282,6 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, flEntries = ts->addedPackages.size + ts->numRemovedPackages; flList = alloca(sizeof(*flList) * (flEntries)); - ht = htCreate(totalFileCount * 2, 0, fpHashFunction, fpEqual); - /* FIXME?: we'd be better off assembling one very large file list and calling fpLookupList only once. I'm not sure that the speedup is worth the trouble though. */ @@ -1151,7 +1293,7 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, i = ts->order[oc].u.addedIndex; alp = ts->addedPackages.list + ts->order[oc].u.addedIndex; - if (!headerGetEntryMinMemory(alp->h, RPMTAG_OLDFILENAMES, NULL, + if (!headerGetEntryMinMemory(alp->h, RPMTAG_COMPFILELIST, NULL, NULL, &fi->fc)) { fi->h = headerLink(alp->h); hdrs[i] = headerLink(fi->h); @@ -1242,6 +1384,8 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, chdir("/"); chroot(ts->root); + ht = htCreate(totalFileCount * 2, 0, fpHashFunction, fpEqual); + /* =============================================== * Add fingerprint for each file not skipped. */ diff --git a/lib/uninstall.c b/lib/uninstall.c index 51f57e982..28b7cb61c 100644 --- a/lib/uninstall.c +++ b/lib/uninstall.c @@ -72,7 +72,7 @@ int removeBinaryPackage(const char * prefix, rpmdb db, unsigned int offset, int i; int fileCount; const char * name, * version, * release; - const char ** fileList; + const char ** baseNameList; int type; int scriptArg; int rc = 0; @@ -131,26 +131,37 @@ int removeBinaryPackage(const char * prefix, rpmdb db, unsigned int offset, flags & RPMTRANS_FLAG_TEST); if (!(flags & RPMTRANS_FLAG_JUSTDB) && - headerGetEntry(h, RPMTAG_OLDFILENAMES, &type, (void **) &fileList, + headerGetEntry(h, RPMTAG_COMPFILELIST, NULL, (void **) &baseNameList, &fileCount)) { const char ** fileMd5List; uint_32 * fileFlagsList; int_16 * fileModesList; + const char ** dirNames; + int_32 * dirIndexes; char * fnbuffer = NULL; int prefixlen = 0; + headerGetEntry(h, RPMTAG_COMPFILEDIRS, NULL, (void **) &dirIndexes, + NULL); + headerGetEntry(h, RPMTAG_COMPDIRLIST, NULL, (void **) &dirNames, + NULL); + /* Get alloca buffer for largest possible prefix + filename. */ if (prefix && prefix[0] != '\0') { int fnbuffersize = 0; size_t fnlen; - prefixlen = strlen(prefix); for (i = 0; i < fileCount; i++) { - if ((fnlen = strlen(fileList[i])) > fnbuffersize) + fnlen = strlen(baseNameList[i]) + + strlen(dirNames[dirIndexes[i]]); + if (fnlen > fnbuffersize) fnbuffersize = fnlen; } - fnbuffersize += strlen(prefix) + sizeof("/"); - fnbuffer = alloca(fnbuffersize); + + prefixlen = strlen(prefix); + fnbuffersize += prefixlen + sizeof("/"); + fnbuffer = alloca(fnbuffersize + 1); + strcpy(fnbuffer, prefix); if (fnbuffer[prefixlen-1] != '/') { fnbuffer[prefixlen++] = '/'; @@ -167,23 +178,28 @@ int removeBinaryPackage(const char * prefix, rpmdb db, unsigned int offset, /* Traverse filelist backwards to help insure that rmdir() will work. */ for (i = fileCount - 1; i >= 0; i--) { - const char * fn; + const char * dirName; + + dirName = dirNames[dirIndexes[i]]; - fn = fileList[i]; if (prefixlen) { - if (*fn == '/') fn++; - strcpy(fnbuffer + prefixlen, fn); - fn = fnbuffer; + if (*dirName == '/') dirName++; + strcpy(fnbuffer + prefixlen, dirName); + } else { + strcpy(fnbuffer, dirName); } + strcat(fnbuffer, baseNameList[i]); rpmMessage(RPMMESS_DEBUG, _(" file: %s action: %s\n"), - fn, fileActionString(actions[i])); + fnbuffer, fileActionString(actions[i])); if (!(flags & RPMTRANS_FLAG_TEST)) - removeFile(fn, fileFlagsList[i], fileModesList[i], actions[i]); + removeFile(fnbuffer, fileFlagsList[i], fileModesList[i], + actions[i]); } - free(fileList); + free(baseNameList); + free(dirNames); free(fileMd5List); } |