summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorewt <devnull@localhost>1999-10-08 20:30:49 +0000
committerewt <devnull@localhost>1999-10-08 20:30:49 +0000
commitcfa9ce427b7c5e2dbb9eba9fe94fff59833d53b3 (patch)
tree08ba2bd84c19d7c895dd4269ece4597c542457b6 /lib
parent568dceb42b2cdaaeafdcab97e155475ef6d1f2b2 (diff)
downloadrpm-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.c32
-rw-r--r--lib/install.c2
-rw-r--r--lib/rpmlib.h4
-rw-r--r--lib/transaction.c224
-rw-r--r--lib/uninstall.c44
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);
}