1998-12-19 03:09:38 +08:00
|
|
|
#include "system.h"
|
|
|
|
|
|
|
|
#include "rpmlib.h"
|
|
|
|
|
|
|
|
#include "depends.h"
|
1998-12-27 02:32:08 +08:00
|
|
|
#include "fprint.h"
|
1998-12-27 00:33:51 +08:00
|
|
|
#include "hash.h"
|
1998-12-19 03:09:38 +08:00
|
|
|
#include "install.h"
|
1999-01-06 11:16:35 +08:00
|
|
|
#include "lookup.h"
|
1999-01-01 03:16:31 +08:00
|
|
|
#include "md5.h"
|
1998-12-19 03:09:38 +08:00
|
|
|
#include "misc.h"
|
1998-12-31 07:03:43 +08:00
|
|
|
#include "rpmdb.h"
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1998-12-27 00:33:51 +08:00
|
|
|
struct fileInfo {
|
1999-01-05 00:44:20 +08:00
|
|
|
/* for all packages */
|
1999-01-01 00:19:42 +08:00
|
|
|
enum fileInfo_e { ADDED, REMOVED } type;
|
1999-01-05 00:44:20 +08:00
|
|
|
enum fileActions * actions;
|
|
|
|
fingerPrint * fps;
|
1999-01-01 03:16:31 +08:00
|
|
|
uint_32 * fflags;
|
1999-01-05 00:44:20 +08:00
|
|
|
char ** fl, ** fmd5s;
|
1999-01-01 03:16:31 +08:00
|
|
|
uint_16 * fmodes;
|
1999-01-05 00:44:20 +08:00
|
|
|
Header h;
|
1998-12-27 00:33:51 +08:00
|
|
|
int fc;
|
1999-01-05 00:44:20 +08:00
|
|
|
/* these are for ADDED packages */
|
|
|
|
char ** flinks;
|
|
|
|
struct availablePackage * ap;
|
1999-01-08 01:06:24 +08:00
|
|
|
struct sharedFileInfo * replaced;
|
1999-01-05 00:44:20 +08:00
|
|
|
/* for REMOVED packages */
|
|
|
|
unsigned int record;
|
1999-01-08 01:06:24 +08:00
|
|
|
char * fstates;
|
1998-12-31 07:03:43 +08:00
|
|
|
};
|
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
static rpmProblemSet psCreate(void);
|
1999-01-08 11:09:57 +08:00
|
|
|
static void psAppend(rpmProblemSet probs, rpmProblemType type,
|
|
|
|
const void * key, Header h, char * str1,
|
|
|
|
Header altHeader);
|
1998-12-19 03:09:38 +08:00
|
|
|
static int archOkay(Header h);
|
|
|
|
static int osOkay(Header h);
|
|
|
|
static Header relocateFileList(struct availablePackage * alp,
|
1999-01-19 11:01:52 +08:00
|
|
|
rpmProblemSet probs, Header h,
|
1999-03-07 01:19:48 +08:00
|
|
|
enum fileActions * actions,
|
|
|
|
int allowBadRelocate);
|
1998-12-19 03:09:38 +08:00
|
|
|
static int psTrim(rpmProblemSet filter, rpmProblemSet target);
|
1998-12-31 07:03:43 +08:00
|
|
|
static int sharedCmp(const void * one, const void * two);
|
1999-01-05 00:44:20 +08:00
|
|
|
static enum fileActions decideFileFate(char * filespec, short dbMode,
|
1999-01-01 03:16:31 +08:00
|
|
|
char * dbMd5, char * dbLink, short newMode,
|
|
|
|
char * newMd5, char * newLink, int newFlags,
|
|
|
|
int brokenMd5);
|
|
|
|
enum fileTypes whatis(short mode);
|
|
|
|
static int filecmp(short mode1, char * md51, char * link1,
|
|
|
|
short mode2, char * md52, char * link2);
|
1999-01-05 00:44:20 +08:00
|
|
|
static int handleInstInstalledFiles(struct fileInfo * fi, rpmdb db,
|
|
|
|
struct sharedFileInfo * shared,
|
1999-01-05 03:11:04 +08:00
|
|
|
int sharedCount, int reportConflicts,
|
|
|
|
rpmProblemSet probs);
|
1999-01-05 00:44:20 +08:00
|
|
|
static int handleRmvdInstalledFiles(struct fileInfo * fi, rpmdb db,
|
|
|
|
struct sharedFileInfo * shared,
|
|
|
|
int sharedCount);
|
|
|
|
void handleOverlappedFiles(struct fileInfo * fi, hashTable ht,
|
|
|
|
rpmProblemSet probs);
|
1999-02-17 12:32:55 +08:00
|
|
|
static int ensureOlder(rpmdb db, Header new, int dbOffset, rpmProblemSet probs,
|
|
|
|
const void * key);
|
1999-02-21 11:34:52 +08:00
|
|
|
static void skipFiles(struct fileInfo * fi, int noDocs);
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-03-01 02:36:19 +08:00
|
|
|
static void freeFi(struct fileInfo *fi)
|
|
|
|
{
|
|
|
|
if (fi->h) {
|
|
|
|
headerFree(fi->h); fi->h = NULL;
|
|
|
|
}
|
|
|
|
if (fi->actions) {
|
|
|
|
free(fi->actions); fi->actions = NULL;
|
|
|
|
}
|
|
|
|
if (fi->replaced) {
|
|
|
|
free(fi->replaced); fi->replaced = NULL;
|
|
|
|
}
|
|
|
|
if (fi->fl) {
|
|
|
|
free(fi->fl); fi->fl = NULL;
|
|
|
|
}
|
|
|
|
if (fi->flinks) {
|
|
|
|
free(fi->flinks); fi->flinks = NULL;
|
|
|
|
}
|
|
|
|
if (fi->fmd5s) {
|
|
|
|
free(fi->fmd5s); fi->fmd5s = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void freeFl(rpmTransactionSet ts, struct fileInfo *flList)
|
|
|
|
{
|
|
|
|
struct availableList * al = &ts->addedPackages;
|
|
|
|
struct availablePackage * alp;
|
|
|
|
struct fileInfo *fi;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (alp = al->list, fi = flList; (alp - al->list) < al->size;
|
|
|
|
alp++, fi++) {
|
|
|
|
freeFi(fi);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ts->numRemovedPackages; i++, fi++) {
|
|
|
|
freeFi(fi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
#define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
|
|
|
|
|
1999-02-23 08:56:32 +08:00
|
|
|
#define NOTIFY(_x) if (notify) notify _x
|
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
/* Return -1 on error, > 0 if newProbs is set, 0 if everything
|
|
|
|
happened */
|
1999-01-12 11:11:25 +08:00
|
|
|
int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
|
1998-12-19 03:09:38 +08:00
|
|
|
void * notifyData, rpmProblemSet okProbs,
|
1999-03-06 06:41:10 +08:00
|
|
|
rpmProblemSet * newProbs, int flags, int ignoreSet)
|
1999-02-23 06:15:19 +08:00
|
|
|
{
|
1999-01-19 11:01:52 +08:00
|
|
|
int i, j;
|
1998-12-19 03:09:38 +08:00
|
|
|
struct availableList * al = &ts->addedPackages;
|
|
|
|
int rc, ourrc = 0;
|
|
|
|
struct availablePackage * alp;
|
|
|
|
rpmProblemSet probs;
|
1998-12-31 07:03:43 +08:00
|
|
|
dbiIndexSet dbi, * matches;
|
1998-12-19 03:09:38 +08:00
|
|
|
Header * hdrs;
|
1998-12-27 00:33:51 +08:00
|
|
|
int fileCount;
|
|
|
|
int totalFileCount = 0;
|
1999-01-01 00:19:42 +08:00
|
|
|
hashTable ht;
|
|
|
|
struct fileInfo * flList, * fi;
|
1998-12-31 07:03:43 +08:00
|
|
|
struct sharedFileInfo * shared, * sharedList;
|
|
|
|
int numShared;
|
1999-01-05 00:44:20 +08:00
|
|
|
int flEntries;
|
|
|
|
int last;
|
1999-01-05 03:11:04 +08:00
|
|
|
int beingRemoved;
|
1999-01-08 11:09:57 +08:00
|
|
|
char * currDir, * chptr;
|
1999-01-12 11:11:25 +08:00
|
|
|
FD_t fd;
|
1998-12-27 00:33:51 +08:00
|
|
|
|
|
|
|
/* FIXME: what if the same package is included in ts twice? */
|
1998-12-19 03:09:38 +08:00
|
|
|
|
|
|
|
probs = psCreate();
|
|
|
|
*newProbs = probs;
|
|
|
|
hdrs = alloca(sizeof(*hdrs) * al->size);
|
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 1, al->size, NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
for (alp = al->list; (alp - al->list) < al->size; alp++) {
|
1999-03-07 01:19:48 +08:00
|
|
|
if (!archOkay(alp->h) && !(ignoreSet & RPMPROB_FILTER_IGNOREARCH))
|
1999-01-06 11:16:35 +08:00
|
|
|
psAppend(probs, RPMPROB_BADARCH, alp->key, alp->h, NULL, NULL);
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-03-07 01:19:48 +08:00
|
|
|
if (!osOkay(alp->h) && !(ignoreSet & RPMPROB_FILTER_IGNOREOS)) {
|
1999-01-06 11:16:35 +08:00
|
|
|
psAppend(probs, RPMPROB_BADOS, alp->key, alp->h, NULL, NULL);
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((alp->h, RPMCALLBACK_TRANS_PROGRESS, (alp - al->list), al->size,
|
|
|
|
NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-03-07 01:19:48 +08:00
|
|
|
if (!(ignoreSet & RPMPROB_FILTER_OLDPACKAGE)) {
|
|
|
|
rc = rpmdbFindPackage(ts->db, alp->name, &dbi);
|
|
|
|
if (rc == 2) {
|
|
|
|
return -1;
|
|
|
|
} else if (!rc) {
|
|
|
|
for (i = 0; i < dbi.count; i++)
|
|
|
|
ensureOlder(ts->db, alp->h, dbi.recs[i].recOffset,
|
|
|
|
probs, alp->key);
|
1999-02-17 12:32:55 +08:00
|
|
|
|
1999-03-07 01:19:48 +08:00
|
|
|
dbiFreeIndexRecord(dbi);
|
|
|
|
}
|
1999-02-17 12:32:55 +08:00
|
|
|
}
|
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
rc = findMatches(ts->db, alp->name, alp->version, alp->release, &dbi);
|
|
|
|
if (rc == 2) {
|
|
|
|
return -1;
|
|
|
|
} else if (!rc) {
|
1999-03-07 01:19:48 +08:00
|
|
|
if (!(ignoreSet & RPMPROB_FILTER_REPLACEPKG))
|
|
|
|
psAppend(probs, RPMPROB_PKG_INSTALLED, alp->key, alp->h, NULL,
|
|
|
|
NULL);
|
1998-12-19 03:09:38 +08:00
|
|
|
dbiFreeIndexRecord(dbi);
|
|
|
|
}
|
|
|
|
|
1998-12-27 00:33:51 +08:00
|
|
|
if (headerGetEntry(alp->h, RPMTAG_FILENAMES, NULL, NULL, &fileCount))
|
|
|
|
totalFileCount += fileCount;
|
|
|
|
}
|
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 1, al->size, NULL, notifyData));
|
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 2, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
/* FIXME: it seems a bit silly to read in all of these headers twice */
|
1999-02-25 10:41:22 +08:00
|
|
|
for (i = 0; i < ts->numRemovedPackages; i++) {
|
1999-01-05 00:44:20 +08:00
|
|
|
Header h;
|
|
|
|
|
|
|
|
if ((h = rpmdbGetRecord(ts->db, ts->removedPackages[i]))) {
|
|
|
|
if (headerGetEntry(h, RPMTAG_FILENAMES, NULL, NULL,
|
|
|
|
&fileCount))
|
|
|
|
totalFileCount += fileCount;
|
1999-03-01 02:36:19 +08:00
|
|
|
headerFree(h); /* XXX ==> LEAK */
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((h, RPMCALLBACK_TRANS_PROGRESS, i, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
1999-03-06 06:41:10 +08:00
|
|
|
|
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 2, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1999-01-05 00:44:20 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
flEntries = al->size + ts->numRemovedPackages;
|
|
|
|
flList = alloca(sizeof(*flList) * (flEntries));
|
1998-12-27 00:33:51 +08:00
|
|
|
|
1998-12-27 02:32:08 +08:00
|
|
|
ht = htCreate(totalFileCount * 2, 0, fpHashFunction, fpEqual);
|
1998-12-31 00:59:54 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 3, al->size, NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
/* FIXME?: we'd be better off assembling one very large file list and
|
1998-12-31 00:59:54 +08:00
|
|
|
calling fpLookupList only once. I'm not sure that the speedup is
|
|
|
|
worth the trouble though. */
|
1999-01-19 11:01:52 +08:00
|
|
|
for (fi = flList, alp = al->list; (alp - al->list) < al->size;
|
|
|
|
fi++, alp++) {
|
|
|
|
if (!headerGetEntryMinMemory(alp->h, RPMTAG_FILENAMES, NULL,
|
|
|
|
(void *) NULL, &fi->fc)) {
|
1999-02-25 10:41:22 +08:00
|
|
|
fi->replaced = NULL;
|
|
|
|
fi->actions = NULL;
|
1999-01-19 11:01:52 +08:00
|
|
|
fi->fc = 0;
|
|
|
|
fi->h = alp->h;
|
1999-02-08 07:14:04 +08:00
|
|
|
hdrs[alp - al->list] = headerLink(fi->h);
|
1998-12-27 00:33:51 +08:00
|
|
|
continue;
|
1999-01-19 11:01:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fi->actions = calloc(sizeof(*fi->actions), fi->fc);
|
|
|
|
fi->h = hdrs[alp - al->list] = relocateFileList(alp, probs, alp->h,
|
1999-03-07 01:19:48 +08:00
|
|
|
fi->actions, ignoreSet & RPMPROB_FILTER_FORCERELOCATE);
|
1999-01-19 11:01:52 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((fi->h, RPMCALLBACK_TRANS_PROGRESS, (alp - al->list), al->size,
|
|
|
|
NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILENAMES, NULL,
|
|
|
|
(void *) &fi->fl, &fi->fc);
|
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILEMD5S, NULL,
|
1998-12-27 02:32:08 +08:00
|
|
|
(void *) &fi->fmd5s, NULL);
|
1999-01-05 00:44:20 +08:00
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILELINKTOS, NULL,
|
1999-01-01 00:19:42 +08:00
|
|
|
(void *) &fi->flinks, NULL);
|
1999-01-05 00:44:20 +08:00
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILEMODES, NULL,
|
1999-01-01 03:16:31 +08:00
|
|
|
(void *) &fi->fmodes, NULL);
|
1999-01-05 00:44:20 +08:00
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILEFLAGS, NULL,
|
1999-01-01 03:16:31 +08:00
|
|
|
(void *) &fi->fflags, NULL);
|
1998-12-27 00:33:51 +08:00
|
|
|
|
1999-02-21 11:34:52 +08:00
|
|
|
skipFiles(fi, flags & RPMTRANS_FLAG_NODOCS);
|
|
|
|
|
1999-01-01 00:19:42 +08:00
|
|
|
fi->type = ADDED;
|
1999-03-07 02:43:49 +08:00
|
|
|
fi->fps = malloc(fi->fc * sizeof(*fi->fps));
|
1999-01-05 00:44:20 +08:00
|
|
|
fi->ap = alp;
|
1999-01-08 01:06:24 +08:00
|
|
|
fi->replaced = NULL;
|
1998-12-27 00:33:51 +08:00
|
|
|
}
|
1998-12-31 00:59:54 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 3, al->size, NULL, notifyData));
|
|
|
|
|
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 4, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
for (i = 0; i < ts->numRemovedPackages; i++, fi++) {
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-02-25 10:41:22 +08:00
|
|
|
fi->actions = NULL;
|
|
|
|
fi->replaced = NULL;
|
1999-01-05 00:44:20 +08:00
|
|
|
fi->type = REMOVED;
|
|
|
|
fi->record = ts->removedPackages[i];
|
|
|
|
fi->h = rpmdbGetRecord(ts->db, fi->record);
|
|
|
|
if (!fi->h) {
|
|
|
|
/* ACK! */
|
|
|
|
continue;
|
|
|
|
}
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((fi->h, RPMCALLBACK_TRANS_PROGRESS, i, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
if (!headerGetEntryMinMemory(fi->h, RPMTAG_FILENAMES, NULL,
|
|
|
|
(void *) &fi->fl, &fi->fc)) {
|
1999-01-19 11:01:52 +08:00
|
|
|
fi->fc = 0;
|
1999-01-05 00:44:20 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILEFLAGS, NULL,
|
|
|
|
(void *) &fi->fflags, NULL);
|
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILEMD5S, NULL,
|
|
|
|
(void *) &fi->fmd5s, NULL);
|
1999-03-01 02:36:19 +08:00
|
|
|
|
|
|
|
fi->flinks = NULL; /* XXX FIXME W2DO? */
|
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILEMODES, NULL,
|
|
|
|
(void *) &fi->fmodes, NULL);
|
1999-01-08 01:06:24 +08:00
|
|
|
headerGetEntryMinMemory(fi->h, RPMTAG_FILESTATES, NULL,
|
|
|
|
(void *) &fi->fstates, NULL);
|
1998-12-27 00:33:51 +08:00
|
|
|
|
1999-02-21 11:34:52 +08:00
|
|
|
/* Note that as FA_UNKNOWN = 0, this does the right thing */
|
1999-01-19 11:01:52 +08:00
|
|
|
fi->actions = calloc(sizeof(*fi->actions), fi->fc);
|
1999-03-07 02:43:49 +08:00
|
|
|
fi->fps = malloc(fi->fc * sizeof(*fi->fps));
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
1999-03-06 06:41:10 +08:00
|
|
|
|
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 4, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1998-12-27 00:33:51 +08:00
|
|
|
|
1999-01-08 11:09:57 +08:00
|
|
|
chptr = currentDirectory();
|
|
|
|
currDir = alloca(strlen(chptr) + 1);
|
|
|
|
strcpy(currDir, chptr);
|
|
|
|
free(chptr);
|
|
|
|
chdir("/");
|
|
|
|
chroot(ts->root);
|
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 5, flEntries, NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-02-08 04:09:27 +08:00
|
|
|
for (fi = flList; (fi - flList) < flEntries; fi++) {
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_PROGRESS, (fi - flList), flEntries,
|
|
|
|
NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-02-08 04:09:27 +08:00
|
|
|
fpLookupList(fi->fl, fi->fps, fi->fc, 1);
|
|
|
|
for (i = 0; i < fi->fc; i++) {
|
1999-02-21 11:34:52 +08:00
|
|
|
if (fi->actions[i] != FA_SKIP && fi->actions[i] != FA_SKIPNSTATE)
|
|
|
|
htAddEntry(ht, fi->fps + i, fi);
|
1999-02-08 04:09:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 5, flEntries, NULL, notifyData));
|
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 6, flEntries, NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
for (fi = flList; (fi - flList) < flEntries; fi++) {
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_PROGRESS, (fi - flList), flEntries,
|
|
|
|
NULL, notifyData));
|
|
|
|
|
1998-12-31 07:03:43 +08:00
|
|
|
matches = malloc(sizeof(*matches) * fi->fc);
|
|
|
|
if (rpmdbFindFpList(ts->db, fi->fps, matches, fi->fc)) return 1;
|
|
|
|
|
|
|
|
numShared = 0;
|
|
|
|
for (i = 0; i < fi->fc; i++)
|
|
|
|
numShared += matches[i].count;
|
|
|
|
|
|
|
|
shared = sharedList = malloc(sizeof(*sharedList) * (numShared + 1));
|
|
|
|
for (i = 0; i < fi->fc; i++) {
|
|
|
|
for (j = 0; j < matches[i].count; j++) {
|
|
|
|
shared->pkgFileNum = i;
|
|
|
|
shared->otherPkg = matches[i].recs[j].recOffset;
|
|
|
|
shared->otherFileNum = matches[i].recs[j].fileNumber;
|
|
|
|
shared++;
|
|
|
|
}
|
1999-02-25 07:55:00 +08:00
|
|
|
dbiFreeIndexRecord(matches[i]);
|
1998-12-31 07:03:43 +08:00
|
|
|
}
|
|
|
|
shared->otherPkg = -1;
|
|
|
|
free(matches);
|
|
|
|
|
|
|
|
qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (i < numShared) {
|
1999-01-05 00:44:20 +08:00
|
|
|
last = i + 1;
|
|
|
|
j = sharedList[i].otherPkg;
|
|
|
|
while ((sharedList[last].otherPkg == j) && (last < numShared))
|
|
|
|
last++;
|
|
|
|
last--;
|
|
|
|
|
1999-02-25 10:41:22 +08:00
|
|
|
for (j = 0; j < ts->numRemovedPackages; j++) {
|
1999-01-05 00:44:20 +08:00
|
|
|
if (ts->removedPackages[j] == sharedList[i].otherPkg)
|
|
|
|
break;
|
1999-02-25 10:41:22 +08:00
|
|
|
}
|
1999-01-05 03:11:04 +08:00
|
|
|
beingRemoved = (j < ts->numRemovedPackages);
|
1998-12-31 00:59:54 +08:00
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
if (fi->type == ADDED)
|
1999-01-05 03:11:04 +08:00
|
|
|
handleInstInstalledFiles(fi, ts->db, sharedList + i,
|
1999-03-07 01:19:48 +08:00
|
|
|
last - i + 1,
|
|
|
|
!(beingRemoved ||
|
|
|
|
(ignoreSet & RPMPROB_FILTER_REPLACEOLDFILES)),
|
|
|
|
probs);
|
1999-01-05 03:11:04 +08:00
|
|
|
else if (fi->type == REMOVED && !beingRemoved)
|
|
|
|
handleRmvdInstalledFiles(fi, ts->db, sharedList + i,
|
|
|
|
last - i + 1);
|
1998-12-31 07:03:43 +08:00
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
i = last + 1;
|
1998-12-27 00:33:51 +08:00
|
|
|
}
|
|
|
|
|
1998-12-31 07:03:43 +08:00
|
|
|
free(sharedList);
|
|
|
|
|
1999-03-07 01:19:48 +08:00
|
|
|
handleOverlappedFiles(fi, ht,
|
|
|
|
(ignoreSet & RPMPROB_FILTER_REPLACENEWFILES) ? NULL : probs);
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 6, flEntries, NULL, notifyData));
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-01-08 11:09:57 +08:00
|
|
|
chroot(".");
|
|
|
|
chdir(currDir);
|
|
|
|
|
1998-12-27 02:32:08 +08:00
|
|
|
htFree(ht);
|
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 7, al->size, NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
for (alp = al->list, fi = flList; (alp - al->list) < al->size;
|
|
|
|
alp++, fi++) {
|
|
|
|
if (fi->fc) {
|
1999-03-01 02:36:19 +08:00
|
|
|
free(fi->fl); fi->fl = NULL;
|
1999-01-19 11:01:52 +08:00
|
|
|
if (fi->type == ADDED) {
|
1999-03-01 02:36:19 +08:00
|
|
|
free(fi->fmd5s); fi->fmd5s = NULL;
|
|
|
|
free(fi->flinks); fi->flinks = NULL;
|
1999-03-07 02:43:49 +08:00
|
|
|
free(fi->fps); fi->fps = NULL;
|
1999-01-19 11:01:52 +08:00
|
|
|
}
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
1998-12-31 00:59:54 +08:00
|
|
|
}
|
1999-03-06 06:41:10 +08:00
|
|
|
|
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 7, al->size, NULL, notifyData));
|
|
|
|
|
1999-01-12 11:11:25 +08:00
|
|
|
if ((flags & RPMTRANS_FLAG_BUILD_PROBS) ||
|
|
|
|
(probs->numProblems && (!okProbs || psTrim(okProbs, probs)))) {
|
1998-12-19 03:09:38 +08:00
|
|
|
*newProbs = probs;
|
1999-01-01 03:16:31 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 8, al->size, NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
for (alp = al->list, fi = flList; (alp - al->list) < al->size;
|
|
|
|
alp++, fi++) {
|
1999-03-01 02:36:19 +08:00
|
|
|
if (fi->fc)
|
1999-01-27 01:10:29 +08:00
|
|
|
headerFree(hdrs[alp - al->list]);
|
1999-03-01 02:36:19 +08:00
|
|
|
freeFi(fi); /* XXX ==> LEAK */
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 8, al->size, NULL, notifyData));
|
|
|
|
|
1999-03-01 02:36:19 +08:00
|
|
|
freeFl(ts, flList); /* XXX ==> LEAK */
|
1998-12-19 03:09:38 +08:00
|
|
|
return al->size + ts->numRemovedPackages;
|
|
|
|
}
|
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_START, 9, al->size, NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
for (alp = al->list, fi = flList; (alp - al->list) < al->size;
|
|
|
|
alp++, fi++) {
|
|
|
|
if (alp->fd) {
|
|
|
|
fd = alp->fd;
|
1999-01-12 11:11:25 +08:00
|
|
|
} else {
|
|
|
|
fd = notify(fi->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0,
|
1999-01-19 11:01:52 +08:00
|
|
|
alp->key, notifyData);
|
1999-01-15 11:50:51 +08:00
|
|
|
if (fd) {
|
|
|
|
Header h;
|
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
headerFree(hdrs[alp - al->list]);
|
1999-01-15 11:50:51 +08:00
|
|
|
rc = rpmReadPackageHeader(fd, &h, NULL, NULL, NULL);
|
|
|
|
if (rc) {
|
|
|
|
notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0,
|
1999-01-19 11:01:52 +08:00
|
|
|
alp->key, notifyData);
|
1999-01-15 11:50:51 +08:00
|
|
|
ourrc++;
|
|
|
|
fd = NULL;
|
|
|
|
} else {
|
1999-01-19 11:01:52 +08:00
|
|
|
hdrs[alp - al->list] =
|
1999-03-07 01:19:48 +08:00
|
|
|
relocateFileList(alp, probs, h, NULL, 1);
|
1999-01-15 11:50:51 +08:00
|
|
|
headerFree(h);
|
|
|
|
}
|
|
|
|
}
|
1999-01-12 11:11:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fd) {
|
1999-01-19 11:01:52 +08:00
|
|
|
if (installBinaryPackage(ts->root, ts->db, fd,
|
1999-02-17 11:42:57 +08:00
|
|
|
hdrs[alp - al->list], flags, notify,
|
1999-01-19 11:01:52 +08:00
|
|
|
notifyData, alp->key, fi->actions,
|
1999-02-08 04:09:27 +08:00
|
|
|
fi->fc ? fi->replaced : NULL,
|
|
|
|
ts->scriptFd))
|
1999-01-12 11:11:25 +08:00
|
|
|
ourrc++;
|
|
|
|
} else {
|
1998-12-19 03:09:38 +08:00
|
|
|
ourrc++;
|
1999-01-12 11:11:25 +08:00
|
|
|
}
|
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
headerFree(hdrs[alp - al->list]);
|
1999-01-01 03:16:31 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
if (!alp->fd && fd)
|
|
|
|
notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, alp->key,
|
|
|
|
notifyData);
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 9, al->size, NULL, notifyData));
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((NULL, RPMCALLBACK_UNINST_START, 0, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
/* fi is left at the first package which is to be removed */
|
1999-01-05 00:44:20 +08:00
|
|
|
for (i = 0; i < ts->numRemovedPackages; i++, fi++) {
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1999-03-06 06:41:10 +08:00
|
|
|
NOTIFY((fi->h, RPMCALLBACK_UNINST_PROGRESS, i, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
if (removeBinaryPackage(ts->root, ts->db, ts->removedPackages[i],
|
1999-02-17 11:42:57 +08:00
|
|
|
flags, fi->actions, ts->scriptFd))
|
1999-02-23 06:15:19 +08:00
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
ourrc++;
|
1999-02-25 07:55:00 +08:00
|
|
|
}
|
1999-03-06 06:41:10 +08:00
|
|
|
|
|
|
|
NOTIFY((NULL, RPMCALLBACK_UNINST_STOP, 0, ts->numRemovedPackages,
|
|
|
|
NULL, notifyData));
|
1999-02-25 07:55:00 +08:00
|
|
|
|
1999-03-01 02:36:19 +08:00
|
|
|
freeFl(ts, flList); /* XXX ==> LEAK */
|
|
|
|
|
1999-01-01 03:16:31 +08:00
|
|
|
if (ourrc)
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
return 0;
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
|
|
|
|
1999-02-08 04:09:27 +08:00
|
|
|
void rpmtransSetScriptFd(rpmTransactionSet ts, FD_t fd) {
|
|
|
|
ts->scriptFd = fd;
|
|
|
|
}
|
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
static rpmProblemSet psCreate(void) {
|
|
|
|
rpmProblemSet probs;
|
|
|
|
|
|
|
|
probs = malloc(sizeof(*probs));
|
|
|
|
probs->numProblems = probs->numProblemsAlloced = 0;
|
|
|
|
probs->probs = NULL;
|
|
|
|
|
|
|
|
return probs;
|
|
|
|
}
|
|
|
|
|
1999-01-08 11:09:57 +08:00
|
|
|
static void psAppend(rpmProblemSet probs, rpmProblemType type,
|
|
|
|
const void * key, Header h, char * str1, Header altH) {
|
1998-12-19 03:09:38 +08:00
|
|
|
if (probs->numProblems == probs->numProblemsAlloced) {
|
|
|
|
if (probs->numProblemsAlloced)
|
|
|
|
probs->numProblemsAlloced *= 2;
|
|
|
|
else
|
|
|
|
probs->numProblemsAlloced = 2;
|
|
|
|
probs->probs = realloc(probs->probs,
|
|
|
|
probs->numProblemsAlloced * sizeof(*probs->probs));
|
|
|
|
}
|
|
|
|
|
|
|
|
probs->probs[probs->numProblems].type = type;
|
|
|
|
probs->probs[probs->numProblems].key = key;
|
|
|
|
probs->probs[probs->numProblems].h = headerLink(h);
|
1999-01-01 00:19:42 +08:00
|
|
|
if (str1)
|
|
|
|
probs->probs[probs->numProblems].str1 = strdup(str1);
|
|
|
|
else
|
|
|
|
probs->probs[probs->numProblems].str1 = NULL;
|
1999-01-06 11:16:35 +08:00
|
|
|
|
|
|
|
if (altH)
|
|
|
|
probs->probs[probs->numProblems].altH = headerLink(altH);
|
|
|
|
else
|
|
|
|
probs->probs[probs->numProblems].altH = NULL;
|
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
probs->probs[probs->numProblems++].ignoreProblem = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int archOkay(Header h) {
|
|
|
|
int_8 * pkgArchNum;
|
|
|
|
void * pkgArch;
|
|
|
|
int type, count, archNum;
|
|
|
|
|
|
|
|
/* make sure we're trying to install this on the proper architecture */
|
|
|
|
headerGetEntry(h, RPMTAG_ARCH, &type, (void **) &pkgArch, &count);
|
|
|
|
if (type == RPM_INT8_TYPE) {
|
|
|
|
/* old arch handling */
|
|
|
|
rpmGetArchInfo(NULL, &archNum);
|
|
|
|
pkgArchNum = pkgArch;
|
|
|
|
if (archNum != *pkgArchNum) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* new arch handling */
|
|
|
|
if (!rpmMachineScore(RPM_MACHTABLE_INSTARCH, pkgArch)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int osOkay(Header h) {
|
|
|
|
void * pkgOs;
|
|
|
|
int type, count;
|
|
|
|
|
|
|
|
/* make sure we're trying to install this on the proper os */
|
|
|
|
headerGetEntry(h, RPMTAG_OS, &type, (void **) &pkgOs, &count);
|
|
|
|
if (type == RPM_INT8_TYPE) {
|
|
|
|
/* v1 packages and v2 packages both used improper OS numbers, so just
|
|
|
|
deal with it hope things work */
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
/* new os handling */
|
|
|
|
if (!rpmMachineScore(RPM_MACHTABLE_INSTOS, pkgOs)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpmProblemSetFree(rpmProblemSet probs) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < probs->numProblems; i++) {
|
|
|
|
headerFree(probs->probs[i].h);
|
|
|
|
if (probs->probs[i].str1) free(probs->probs[i].str1);
|
|
|
|
}
|
|
|
|
free(probs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Header relocateFileList(struct availablePackage * alp,
|
1999-01-19 11:01:52 +08:00
|
|
|
rpmProblemSet probs, Header origH,
|
1999-03-07 01:19:48 +08:00
|
|
|
enum fileActions * actions,
|
|
|
|
int allowBadRelocate) {
|
1998-12-19 03:09:38 +08:00
|
|
|
int numValid, numRelocations;
|
|
|
|
int i, j, madeSwap, rc;
|
|
|
|
rpmRelocation * nextReloc, * relocations = NULL;
|
|
|
|
rpmRelocation * rawRelocations = alp->relocs;
|
|
|
|
rpmRelocation tmpReloc;
|
|
|
|
char ** validRelocations, ** actualRelocations;
|
|
|
|
char ** names;
|
1999-01-19 11:01:52 +08:00
|
|
|
char ** origNames;
|
1999-02-21 12:01:12 +08:00
|
|
|
int len;
|
1998-12-19 03:09:38 +08:00
|
|
|
char * newName;
|
|
|
|
int_32 fileCount;
|
|
|
|
Header h;
|
1999-01-19 11:01:52 +08:00
|
|
|
int relocated = 0;
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-01-15 11:50:51 +08:00
|
|
|
if (!rawRelocations) return headerLink(origH);
|
|
|
|
h = headerCopy(origH);
|
1998-12-19 03:09:38 +08:00
|
|
|
|
|
|
|
if (!headerGetEntry(h, RPMTAG_PREFIXES, NULL,
|
|
|
|
(void **) &validRelocations, &numValid))
|
|
|
|
numValid = 0;
|
|
|
|
|
1999-01-20 00:24:57 +08:00
|
|
|
for (i = 0; rawRelocations[i].newPath || rawRelocations[i].oldPath; i++) ;
|
1998-12-19 03:09:38 +08:00
|
|
|
numRelocations = i;
|
|
|
|
relocations = alloca(sizeof(*relocations) * numRelocations);
|
|
|
|
|
|
|
|
/* FIXME? this code assumes the validRelocations array won't
|
|
|
|
have trailing /'s in it */
|
|
|
|
/* FIXME: all of this needs to be tested with an old format
|
|
|
|
relocateable package */
|
|
|
|
|
|
|
|
for (i = 0; i < numRelocations; i++) {
|
|
|
|
/* FIXME: default relocations (oldPath == NULL) need to be handled
|
1999-01-19 11:01:52 +08:00
|
|
|
in the UI, not rpmlib */
|
1998-12-19 03:09:38 +08:00
|
|
|
|
|
|
|
relocations[i].oldPath =
|
|
|
|
alloca(strlen(rawRelocations[i].oldPath) + 1);
|
|
|
|
strcpy(relocations[i].oldPath, rawRelocations[i].oldPath);
|
|
|
|
stripTrailingSlashes(relocations[i].oldPath);
|
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
if (rawRelocations[i].newPath) {
|
|
|
|
relocations[i].newPath =
|
|
|
|
alloca(strlen(rawRelocations[i].newPath) + 1);
|
|
|
|
strcpy(relocations[i].newPath, rawRelocations[i].newPath);
|
|
|
|
stripTrailingSlashes(relocations[i].newPath);
|
|
|
|
} else {
|
|
|
|
relocations[i].newPath = NULL;
|
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-01-20 00:24:57 +08:00
|
|
|
if (relocations[i].newPath) {
|
|
|
|
for (j = 0; j < numValid; j++)
|
|
|
|
if (!strcmp(validRelocations[j],
|
|
|
|
relocations[i].oldPath)) break;
|
1999-03-07 01:19:48 +08:00
|
|
|
if (j == numValid && !allowBadRelocate)
|
1999-01-20 00:24:57 +08:00
|
|
|
psAppend(probs, RPMPROB_BADRELOCATE, alp->key, alp->h,
|
|
|
|
relocations[i].oldPath, NULL);
|
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* stupid bubble sort, but it's probably faster here */
|
|
|
|
for (i = 0; i < numRelocations; i++) {
|
|
|
|
madeSwap = 0;
|
|
|
|
for (j = 1; j < numRelocations; j++) {
|
|
|
|
if (strcmp(relocations[j - 1].oldPath,
|
|
|
|
relocations[j].oldPath) > 0) {
|
|
|
|
tmpReloc = relocations[j - 1];
|
|
|
|
relocations[j - 1] = relocations[j];
|
|
|
|
relocations[j] = tmpReloc;
|
|
|
|
madeSwap = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!madeSwap) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numValid) {
|
|
|
|
actualRelocations = malloc(sizeof(*actualRelocations) * numValid);
|
|
|
|
for (i = 0; i < numValid; i++) {
|
|
|
|
for (j = 0; j < numRelocations; j++) {
|
|
|
|
if (!strcmp(validRelocations[i], relocations[j].oldPath)) {
|
|
|
|
actualRelocations[i] = relocations[j].newPath;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == numRelocations)
|
|
|
|
actualRelocations[i] = validRelocations[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
headerAddEntry(h, RPMTAG_INSTPREFIXES, RPM_STRING_ARRAY_TYPE,
|
|
|
|
(void **) actualRelocations, numValid);
|
|
|
|
|
|
|
|
free(actualRelocations);
|
|
|
|
free(validRelocations);
|
|
|
|
}
|
|
|
|
|
|
|
|
headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &names,
|
|
|
|
&fileCount);
|
|
|
|
|
|
|
|
/* go through things backwards so that /usr/local relocations take
|
|
|
|
precedence over /usr ones */
|
1999-02-21 12:01:12 +08:00
|
|
|
for (i = fileCount - 1; i >= 0; i--) {
|
|
|
|
for (j = numRelocations - 1; j >= 0; j--) {
|
|
|
|
nextReloc = relocations + j;
|
|
|
|
len = strlen(relocations[j].oldPath);
|
|
|
|
rc = (!strncmp(relocations[j].oldPath, names[i], len) &&
|
|
|
|
((names[i][len] == '/') || !names[i][len]));
|
|
|
|
if (rc) break;
|
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-02-21 12:01:12 +08:00
|
|
|
if (j >= 0) {
|
|
|
|
nextReloc = relocations + j;
|
1999-01-19 11:01:52 +08:00
|
|
|
if (nextReloc->newPath) {
|
1999-02-21 12:01:12 +08:00
|
|
|
newName = alloca(strlen(nextReloc->newPath) +
|
|
|
|
strlen(names[i]) + 1);
|
1999-01-19 11:01:52 +08:00
|
|
|
strcpy(newName, nextReloc->newPath);
|
|
|
|
strcat(newName, names[i] + len);
|
|
|
|
rpmMessage(RPMMESS_DEBUG, _("relocating %s to %s\n"),
|
|
|
|
names[i], newName);
|
|
|
|
names[i] = newName;
|
|
|
|
relocated = 1;
|
|
|
|
} else if (actions) {
|
1999-02-21 11:34:52 +08:00
|
|
|
actions[i] = FA_SKIPNSTATE;
|
1999-01-20 00:24:57 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("excluding %s\n"), names[i]);
|
1999-01-19 11:01:52 +08:00
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-19 11:01:52 +08:00
|
|
|
if (relocated) {
|
1999-01-20 00:24:57 +08:00
|
|
|
headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &origNames, NULL);
|
1999-01-19 11:01:52 +08:00
|
|
|
headerAddEntry(h, RPMTAG_ORIGFILENAMES, RPM_STRING_ARRAY_TYPE,
|
|
|
|
origNames, fileCount);
|
|
|
|
free(origNames);
|
|
|
|
headerModifyEntry(h, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE,
|
|
|
|
names, fileCount);
|
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
|
|
|
|
free(names);
|
|
|
|
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int psTrim(rpmProblemSet filter, rpmProblemSet target) {
|
|
|
|
/* As the problem sets are generated in an order solely dependent
|
|
|
|
on the ordering of the packages in the transaction, and that
|
|
|
|
ordering can't be changed, the problem sets must be parallel to
|
|
|
|
on another. Additionally, the filter set must be a subset of the
|
|
|
|
target set, given the operations available on transaction set.
|
|
|
|
This is good, as it lets us perform this trim in linear time, rather
|
|
|
|
then logarithmic or quadratic. */
|
|
|
|
rpmProblem * f, * t;
|
|
|
|
int gotProblems = 0;
|
|
|
|
|
|
|
|
f = filter->probs;
|
|
|
|
t = target->probs;
|
|
|
|
|
|
|
|
while ((f - filter->probs) < filter->numProblems) {
|
|
|
|
if (!f->ignoreProblem) {
|
|
|
|
f++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
while ((t - target->probs) < target->numProblems) {
|
|
|
|
if (f->h == t->h && f->type == t->type && t->key == f->key &&
|
|
|
|
XSTRCMP(f->str1, t->str1))
|
|
|
|
break;
|
|
|
|
t++;
|
|
|
|
gotProblems = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((t - target->probs) == target->numProblems) {
|
|
|
|
/* this can't happen ;-) lets be sane if it doesn though */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
t->ignoreProblem = f->ignoreProblem;
|
|
|
|
t++, f++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((t - target->probs) < target->numProblems)
|
|
|
|
gotProblems = 1;
|
|
|
|
|
|
|
|
return gotProblems;
|
|
|
|
}
|
1998-12-31 07:03:43 +08:00
|
|
|
|
|
|
|
static int sharedCmp(const void * one, const void * two) {
|
|
|
|
const struct sharedFileInfo * a = one;
|
|
|
|
const struct sharedFileInfo * b = two;
|
|
|
|
|
|
|
|
if (a->otherPkg < b->otherPkg)
|
|
|
|
return -1;
|
|
|
|
else if (a->otherPkg > b->otherPkg)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1999-01-01 03:16:31 +08:00
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
static enum fileActions decideFileFate(char * filespec, short dbMode,
|
1999-01-01 03:16:31 +08:00
|
|
|
char * dbMd5, char * dbLink, short newMode,
|
|
|
|
char * newMd5, char * newLink, int newFlags,
|
|
|
|
int brokenMd5) {
|
|
|
|
char buffer[1024];
|
|
|
|
char * dbAttr, * newAttr;
|
|
|
|
enum fileTypes dbWhat, newWhat, diskWhat;
|
|
|
|
struct stat sb;
|
|
|
|
int i, rc;
|
1999-02-21 11:34:52 +08:00
|
|
|
int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;
|
1999-01-01 03:16:31 +08:00
|
|
|
|
|
|
|
if (lstat(filespec, &sb)) {
|
|
|
|
/* the file doesn't exist on the disk create it unless the new
|
|
|
|
package has marked it as missingok */
|
|
|
|
if (newFlags & RPMFILE_MISSINGOK) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s skipped due to missingok flag\n"),
|
|
|
|
filespec);
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_SKIP;
|
1999-01-01 03:16:31 +08:00
|
|
|
} else
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_CREATE;
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
diskWhat = whatis(sb.st_mode);
|
|
|
|
dbWhat = whatis(dbMode);
|
|
|
|
newWhat = whatis(newMode);
|
|
|
|
|
|
|
|
/* RPM >= 2.3.10 shouldn't create config directories -- we'll ignore
|
|
|
|
them in older packages as well */
|
|
|
|
if (newWhat == XDIR)
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_CREATE;
|
1999-01-01 03:16:31 +08:00
|
|
|
|
|
|
|
if (diskWhat != newWhat) {
|
1999-02-17 12:04:53 +08:00
|
|
|
return save;
|
1999-01-01 03:16:31 +08:00
|
|
|
} else if (newWhat != dbWhat && diskWhat != dbWhat) {
|
1999-02-17 12:04:53 +08:00
|
|
|
return save;
|
1999-01-01 03:16:31 +08:00
|
|
|
} else if (dbWhat != newWhat) {
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_CREATE;
|
1999-01-01 03:16:31 +08:00
|
|
|
} else if (dbWhat != LINK && dbWhat != REG) {
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_CREATE;
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dbWhat == REG) {
|
|
|
|
if (brokenMd5)
|
|
|
|
rc = mdfileBroken(filespec, buffer);
|
|
|
|
else
|
|
|
|
rc = mdfile(filespec, buffer);
|
|
|
|
|
|
|
|
if (rc) {
|
|
|
|
/* assume the file has been removed, don't freak */
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_CREATE;
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
dbAttr = dbMd5;
|
|
|
|
newAttr = newMd5;
|
|
|
|
} else /* dbWhat == LINK */ {
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
i = readlink(filespec, buffer, sizeof(buffer) - 1);
|
|
|
|
if (i == -1) {
|
|
|
|
/* assume the file has been removed, don't freak */
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_CREATE;
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
dbAttr = dbLink;
|
|
|
|
newAttr = newLink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* this order matters - we'd prefer to CREATE the file if at all
|
|
|
|
possible in case something else (like the timestamp) has changed */
|
|
|
|
|
|
|
|
if (!strcmp(dbAttr, buffer)) {
|
|
|
|
/* this config file has never been modified, so
|
|
|
|
just replace it */
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_CREATE;
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(dbAttr, newAttr)) {
|
|
|
|
/* this file is the same in all versions of this package */
|
1999-02-21 11:34:52 +08:00
|
|
|
return FA_SKIP;
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* the config file on the disk has been modified, but
|
|
|
|
the ones in the two packages are different. It would
|
|
|
|
be nice if RPM was smart enough to at least try and
|
|
|
|
merge the difference ala CVS, but... */
|
|
|
|
|
1999-02-17 12:04:53 +08:00
|
|
|
return save;
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
enum fileTypes whatis(short mode) {
|
|
|
|
enum fileTypes result;
|
|
|
|
|
|
|
|
if (S_ISDIR(mode))
|
|
|
|
result = XDIR;
|
|
|
|
else if (S_ISCHR(mode))
|
|
|
|
result = CDEV;
|
|
|
|
else if (S_ISBLK(mode))
|
|
|
|
result = BDEV;
|
|
|
|
else if (S_ISLNK(mode))
|
|
|
|
result = LINK;
|
|
|
|
else if (S_ISSOCK(mode))
|
|
|
|
result = SOCK;
|
|
|
|
else if (S_ISFIFO(mode))
|
|
|
|
result = PIPE;
|
|
|
|
else
|
|
|
|
result = REG;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int filecmp(short mode1, char * md51, char * link1,
|
|
|
|
short mode2, char * md52, char * link2) {
|
|
|
|
enum fileTypes what1, what2;
|
|
|
|
|
|
|
|
what1 = whatis(mode1);
|
|
|
|
what2 = whatis(mode2);
|
|
|
|
|
|
|
|
if (what1 != what2) return 1;
|
|
|
|
|
|
|
|
if (what1 == LINK)
|
|
|
|
return strcmp(link1, link2);
|
|
|
|
else if (what1 == REG)
|
|
|
|
return strcmp(md51, md52);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
1999-01-05 00:44:20 +08:00
|
|
|
|
|
|
|
static int handleInstInstalledFiles(struct fileInfo * fi, rpmdb db,
|
|
|
|
struct sharedFileInfo * shared,
|
1999-01-05 03:11:04 +08:00
|
|
|
int sharedCount, int reportConflicts,
|
|
|
|
rpmProblemSet probs) {
|
1999-01-05 00:44:20 +08:00
|
|
|
Header h;
|
|
|
|
int i;
|
|
|
|
char ** otherMd5s, ** otherLinks;
|
|
|
|
char * otherStates;
|
|
|
|
uint_32 * otherFlags;
|
|
|
|
uint_16 * otherModes;
|
|
|
|
int otherFileNum;
|
|
|
|
int fileNum;
|
1999-01-08 01:06:24 +08:00
|
|
|
int numReplaced = 0;
|
1999-01-05 00:44:20 +08:00
|
|
|
|
|
|
|
if (!(h = rpmdbGetRecord(db, shared->otherPkg)))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
headerGetEntryMinMemory(h, RPMTAG_FILEMD5S, NULL,
|
|
|
|
(void **) &otherMd5s, NULL);
|
|
|
|
headerGetEntryMinMemory(h, RPMTAG_FILELINKTOS, NULL,
|
|
|
|
(void **) &otherLinks, NULL);
|
|
|
|
headerGetEntryMinMemory(h, RPMTAG_FILESTATES, NULL,
|
|
|
|
(void **) &otherStates, NULL);
|
|
|
|
headerGetEntryMinMemory(h, RPMTAG_FILEMODES, NULL,
|
|
|
|
(void **) &otherModes, NULL);
|
|
|
|
headerGetEntryMinMemory(h, RPMTAG_FILEFLAGS, NULL,
|
|
|
|
(void **) &otherFlags, NULL);
|
|
|
|
|
1999-01-08 01:06:24 +08:00
|
|
|
fi->replaced = malloc(sizeof(*fi->replaced) * sharedCount);
|
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
for (i = 0; i < sharedCount; i++, shared++) {
|
|
|
|
otherFileNum = shared->otherFileNum;
|
|
|
|
fileNum = shared->pkgFileNum;
|
|
|
|
if (otherStates[otherFileNum] == RPMFILE_STATE_NORMAL) {
|
1999-01-08 01:06:24 +08:00
|
|
|
if (filecmp(otherModes[otherFileNum],
|
1999-01-05 00:44:20 +08:00
|
|
|
otherMd5s[otherFileNum],
|
|
|
|
otherLinks[otherFileNum],
|
|
|
|
fi->fmodes[fileNum],
|
|
|
|
fi->fmd5s[fileNum],
|
|
|
|
fi->flinks[fileNum])) {
|
1999-01-08 01:06:24 +08:00
|
|
|
if (reportConflicts)
|
|
|
|
psAppend(probs, RPMPROB_FILE_CONFLICT, fi->ap->key,
|
|
|
|
fi->ap->h, fi->fl[fileNum], h);
|
|
|
|
if (!(otherFlags[otherFileNum] | fi->fflags[fileNum])
|
|
|
|
& RPMFILE_CONFIG)
|
|
|
|
fi->replaced[numReplaced++] = *shared;
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((otherFlags[otherFileNum] | fi->fflags[fileNum])
|
|
|
|
& RPMFILE_CONFIG) {
|
|
|
|
fi->actions[fileNum] = decideFileFate(fi->fl[fileNum],
|
|
|
|
otherModes[otherFileNum],
|
|
|
|
otherMd5s[otherFileNum],
|
|
|
|
otherLinks[otherFileNum],
|
|
|
|
fi->fmodes[fileNum],
|
|
|
|
fi->fmd5s[fileNum],
|
|
|
|
fi->flinks[fileNum],
|
|
|
|
fi->fflags[fileNum],
|
|
|
|
!headerIsEntry(h, RPMTAG_RPMVERSION));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(otherMd5s);
|
|
|
|
free(otherLinks);
|
|
|
|
headerFree(h);
|
|
|
|
|
1999-01-08 01:06:24 +08:00
|
|
|
fi->replaced = realloc(fi->replaced,
|
|
|
|
sizeof(*fi->replaced) * (numReplaced + 1));
|
|
|
|
fi->replaced[numReplaced].otherPkg = 0;
|
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int handleRmvdInstalledFiles(struct fileInfo * fi, rpmdb db,
|
|
|
|
struct sharedFileInfo * shared,
|
|
|
|
int sharedCount) {
|
|
|
|
Header h;
|
|
|
|
int otherFileNum;
|
|
|
|
int fileNum;
|
|
|
|
char * otherStates;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!(h = rpmdbGetRecord(db, shared->otherPkg)))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
headerGetEntryMinMemory(h, RPMTAG_FILESTATES, NULL,
|
|
|
|
(void **) &otherStates, NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < sharedCount; i++, shared++) {
|
|
|
|
otherFileNum = shared->otherFileNum;
|
|
|
|
fileNum = shared->pkgFileNum;
|
|
|
|
|
|
|
|
if (otherStates[fileNum] == RPMFILE_STATE_NORMAL)
|
1999-02-21 11:34:52 +08:00
|
|
|
fi->actions[fileNum] = FA_SKIP;
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
|
|
|
|
1999-03-05 07:26:51 +08:00
|
|
|
headerFree(h);
|
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleOverlappedFiles(struct fileInfo * fi, hashTable ht,
|
|
|
|
rpmProblemSet probs) {
|
|
|
|
int i, j;
|
1999-02-08 02:36:13 +08:00
|
|
|
struct fileInfo ** recs;
|
1999-01-05 00:44:20 +08:00
|
|
|
int numRecs;
|
|
|
|
int otherPkgNum, otherFileNum;
|
|
|
|
struct stat sb;
|
|
|
|
char mdsum[50];
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
for (i = 0; i < fi->fc; i++) {
|
1999-02-21 11:34:52 +08:00
|
|
|
if (fi->actions[i] == FA_SKIP || fi->actions[i] == FA_SKIPNSTATE)
|
|
|
|
continue;
|
|
|
|
|
1999-01-05 00:44:20 +08:00
|
|
|
htGetEntry(ht, &fi->fps[i], (void ***) &recs, &numRecs, NULL);
|
|
|
|
|
|
|
|
/* We need to figure out the current fate of this file. So,
|
|
|
|
work backwards from this file and look for a final action
|
|
|
|
we can work against. */
|
|
|
|
for (j = 0; recs[j] != fi; j++);
|
|
|
|
|
|
|
|
otherPkgNum = j - 1;
|
|
|
|
otherFileNum = -1; /* keep gcc quiet */
|
|
|
|
while (otherPkgNum >= 0) {
|
1999-01-06 11:56:31 +08:00
|
|
|
if (recs[otherPkgNum]->type == ADDED) {
|
|
|
|
/* TESTME: there are more efficient searches in the world... */
|
|
|
|
for (otherFileNum = 0; otherFileNum < recs[otherPkgNum]->fc;
|
|
|
|
otherFileNum++)
|
|
|
|
if (FP_EQUAL(fi->fps[i],
|
|
|
|
recs[otherPkgNum]->fps[otherFileNum]))
|
|
|
|
break;
|
|
|
|
if ((otherFileNum >= 0) &&
|
1999-02-21 11:34:52 +08:00
|
|
|
(recs[otherPkgNum]->actions[otherFileNum] != FA_UNKNOWN))
|
1999-01-05 00:44:20 +08:00
|
|
|
break;
|
1999-01-06 11:56:31 +08:00
|
|
|
}
|
1999-01-05 00:44:20 +08:00
|
|
|
otherPkgNum--;
|
|
|
|
}
|
|
|
|
|
1999-02-08 02:36:13 +08:00
|
|
|
if (fi->type == ADDED && otherPkgNum < 0) {
|
1999-02-21 11:34:52 +08:00
|
|
|
if (fi->actions[i] == FA_UNKNOWN) {
|
1999-01-05 00:44:20 +08:00
|
|
|
if ((fi->fflags[i] & RPMFILE_CONFIG) &&
|
|
|
|
!lstat(fi->fl[i], &sb))
|
1999-02-21 11:34:52 +08:00
|
|
|
fi->actions[i] = FA_BACKUP;
|
1999-01-05 00:44:20 +08:00
|
|
|
else
|
1999-02-21 11:34:52 +08:00
|
|
|
fi->actions[i] = FA_CREATE;
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
|
|
|
} else if (fi->type == ADDED) {
|
1999-03-07 01:19:48 +08:00
|
|
|
if (probs && filecmp(recs[otherPkgNum]->fmodes[otherFileNum],
|
1999-02-08 02:36:13 +08:00
|
|
|
recs[otherPkgNum]->fmd5s[otherFileNum],
|
|
|
|
recs[otherPkgNum]->flinks[otherFileNum],
|
1999-01-05 00:44:20 +08:00
|
|
|
fi->fmodes[i],
|
|
|
|
fi->fmd5s[i],
|
|
|
|
fi->flinks[i])) {
|
|
|
|
psAppend(probs, RPMPROB_NEW_FILE_CONFLICT, fi->ap->key,
|
1999-02-08 02:36:13 +08:00
|
|
|
fi->ap->h, fi->fl[i], recs[otherPkgNum]->ap->h);
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: is this right??? it locks us into the config
|
|
|
|
file handling choice we already made, which may very
|
1999-02-17 11:46:57 +08:00
|
|
|
well be exactly right. What about noreplace files?? */
|
1999-02-21 11:34:52 +08:00
|
|
|
fi->actions[i] = FA_CREATE;
|
1999-02-08 02:36:13 +08:00
|
|
|
} else if (fi->type == REMOVED && otherPkgNum >= 0) {
|
1999-02-21 11:34:52 +08:00
|
|
|
fi->actions[i] = FA_SKIP;
|
1999-01-05 00:44:20 +08:00
|
|
|
} else if (fi->type == REMOVED) {
|
1999-02-21 11:34:52 +08:00
|
|
|
if (fi->actions[i] != FA_SKIP && fi->actions[i] != FA_SKIPNSTATE &&
|
1999-01-08 01:06:24 +08:00
|
|
|
fi->fstates[i] == RPMFILE_STATE_NORMAL ) {
|
1999-01-05 03:11:04 +08:00
|
|
|
if (S_ISREG(fi->fmodes[i]) &&
|
|
|
|
(fi->fflags[i] & RPMFILE_CONFIG)) {
|
|
|
|
rc = mdfile(fi->fl[i], mdsum);
|
|
|
|
if (!rc && strcmp(fi->fmd5s[i], mdsum)) {
|
1999-02-21 11:34:52 +08:00
|
|
|
fi->actions[i] = FA_BACKUP;
|
1999-01-05 03:11:04 +08:00
|
|
|
} else {
|
|
|
|
/* FIXME: config files may need to be saved */
|
1999-02-21 11:34:52 +08:00
|
|
|
fi->actions[i] = FA_REMOVE;
|
1999-01-05 03:11:04 +08:00
|
|
|
}
|
1999-01-05 00:44:20 +08:00
|
|
|
} else {
|
1999-02-21 11:34:52 +08:00
|
|
|
fi->actions[i] = FA_REMOVE;
|
1999-01-05 00:44:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-02-17 12:32:55 +08:00
|
|
|
|
|
|
|
static int ensureOlder(rpmdb db, Header new, int dbOffset, rpmProblemSet probs,
|
|
|
|
const void * key) {
|
|
|
|
Header old;
|
|
|
|
int result, rc = 0;
|
|
|
|
|
|
|
|
old = rpmdbGetRecord(db, dbOffset);
|
|
|
|
if (old == NULL) return 1;
|
|
|
|
|
|
|
|
result = rpmVersionCompare(old, new);
|
|
|
|
if (result <= 0)
|
|
|
|
rc = 0;
|
|
|
|
else if (result > 0) {
|
|
|
|
rc = 1;
|
|
|
|
psAppend(probs, RPMPROB_OLDPACKAGE, key, new, NULL, old);
|
|
|
|
}
|
|
|
|
|
|
|
|
headerFree(old);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
1999-02-21 11:34:52 +08:00
|
|
|
|
|
|
|
static void skipFiles(struct fileInfo * fi, int noDocs) {
|
|
|
|
int i, j;
|
|
|
|
char ** netsharedPaths = NULL, ** nsp;
|
|
|
|
char ** fileLangs, ** languages, ** lang;
|
|
|
|
char * oneLang[2] = { NULL, NULL };
|
|
|
|
int freeLanguages = 0;
|
|
|
|
char * tmpPath, * chptr;
|
|
|
|
|
|
|
|
if (!noDocs)
|
|
|
|
noDocs = rpmGetBooleanVar(RPMVAR_EXCLUDEDOCS);
|
|
|
|
|
|
|
|
if ((tmpPath = rpmGetVar(RPMVAR_NETSHAREDPATH)))
|
|
|
|
netsharedPaths = splitString(tmpPath, strlen(tmpPath), ':');
|
|
|
|
|
|
|
|
if (!headerGetEntry(fi->h, RPMTAG_FILELANGS, NULL, (void **) &fileLangs,
|
|
|
|
NULL))
|
|
|
|
fileLangs = NULL;
|
|
|
|
|
|
|
|
if ((chptr = getenv("LINGUAS"))) {
|
|
|
|
languages = splitString(chptr, strlen(chptr), ':');
|
|
|
|
freeLanguages = 1;
|
|
|
|
} else if ((oneLang[0] = getenv("LANG"))) {
|
|
|
|
languages = oneLang;
|
|
|
|
} else {
|
|
|
|
oneLang[0] = "en";
|
|
|
|
languages = oneLang;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < fi->fc; i++) {
|
|
|
|
if (fi->actions[i] == FA_SKIP || fi->actions[i] == FA_SKIPNSTATE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* netsharedPaths are not relative to the current root (though
|
|
|
|
they do need to take package relocations into account) */
|
|
|
|
for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
|
|
|
|
j = strlen(*nsp);
|
|
|
|
if (!strncmp(fi->fl[i], *nsp, j) &&
|
|
|
|
(fi->fl[i][j] == '\0' ||
|
|
|
|
fi->fl[i][j] == '/'))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nsp && *nsp) {
|
|
|
|
fi->actions[i] = FA_SKIPNSTATE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fileLangs && languages && *fileLangs[i]) {
|
|
|
|
for (lang = languages; *lang; lang++)
|
|
|
|
if (!strcmp(*lang, fileLangs[i])) break;
|
|
|
|
if (!*lang) {
|
|
|
|
fi->actions[i] = FA_SKIPNSTATE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (noDocs && (fi->fflags[i] & RPMFILE_DOC))
|
|
|
|
fi->actions[i] = FA_SKIPNSTATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netsharedPaths) freeSplitString(netsharedPaths);
|
|
|
|
if (fileLangs) free(fileLangs);
|
|
|
|
if (freeLanguages) freeSplitString(languages);
|
|
|
|
}
|