2002-05-17 00:55:21 +08:00
|
|
|
/** \ingroup rpmts
|
2000-08-28 03:40:35 +08:00
|
|
|
* \file lib/transaction.c
|
|
|
|
*/
|
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
#include "system.h"
|
|
|
|
|
2008-01-30 19:53:51 +08:00
|
|
|
#include <rpm/rpmlib.h> /* rpmMachineScore, rpmReadPackageFile */
|
2007-12-08 20:02:32 +08:00
|
|
|
#include <rpm/rpmmacro.h> /* XXX for rpmExpand */
|
|
|
|
#include <rpm/rpmlog.h>
|
|
|
|
#include <rpm/rpmdb.h>
|
|
|
|
#include <rpm/rpmds.h>
|
2008-01-30 23:05:29 +08:00
|
|
|
#include <rpm/rpmfileutil.h>
|
|
|
|
#include <rpm/rpmstring.h>
|
2002-05-20 07:37:24 +08:00
|
|
|
|
2008-05-12 17:28:12 +08:00
|
|
|
#include "lib/fprint.h"
|
2010-05-21 20:36:03 +08:00
|
|
|
#include "lib/misc.h"
|
2010-05-31 19:07:46 +08:00
|
|
|
#include "lib/rpmchroot.h"
|
2007-11-23 18:39:29 +08:00
|
|
|
#include "lib/rpmlock.h"
|
2008-12-19 21:05:54 +08:00
|
|
|
#include "lib/rpmfi_internal.h" /* only internal apis */
|
2008-11-27 16:48:22 +08:00
|
|
|
#include "lib/rpmte_internal.h" /* only internal apis */
|
2007-11-23 18:39:29 +08:00
|
|
|
#include "lib/rpmts_internal.h"
|
2009-01-15 16:28:13 +08:00
|
|
|
#include "rpmio/rpmhook.h"
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2009-12-14 21:23:28 +08:00
|
|
|
/* XXX FIXME: merge with existing (broken?) tests in system.h */
|
|
|
|
/* portability fiddles */
|
|
|
|
#if STATFS_IN_SYS_STATVFS
|
|
|
|
#include <sys/statvfs.h>
|
|
|
|
|
|
|
|
#else
|
|
|
|
# if STATFS_IN_SYS_VFS
|
|
|
|
# include <sys/vfs.h>
|
|
|
|
# else
|
|
|
|
# if STATFS_IN_SYS_MOUNT
|
|
|
|
# include <sys/mount.h>
|
|
|
|
# else
|
|
|
|
# if STATFS_IN_SYS_STATFS
|
|
|
|
# include <sys/statfs.h>
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
|
|
|
|
2009-12-14 21:23:28 +08:00
|
|
|
struct diskspaceInfo_s {
|
2010-02-03 18:45:21 +08:00
|
|
|
char * mntPoint; /*!< File system mount point */
|
2009-12-14 21:23:28 +08:00
|
|
|
dev_t dev; /*!< File system device number. */
|
|
|
|
int64_t bneeded; /*!< No. of blocks needed. */
|
|
|
|
int64_t ineeded; /*!< No. of inodes needed. */
|
|
|
|
int64_t bsize; /*!< File system block size. */
|
|
|
|
int64_t bavail; /*!< No. of blocks available. */
|
|
|
|
int64_t iavail; /*!< No. of inodes available. */
|
|
|
|
int64_t obneeded; /*!< Bookkeeping to avoid duplicate reports */
|
|
|
|
int64_t oineeded; /*!< Bookkeeping to avoid duplicate reports */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Adjust for root only reserved space. On linux e2fs, this is 5%. */
|
|
|
|
#define adj_fs_blocks(_nb) (((_nb) * 21) / 20)
|
|
|
|
#define BLOCK_ROUND(size, block) (((size) + (block) - 1) / (block))
|
|
|
|
|
|
|
|
static int rpmtsInitDSI(const rpmts ts)
|
|
|
|
{
|
|
|
|
if (rpmtsFilterFlags(ts) & RPMPROB_FILTER_DISKSPACE)
|
|
|
|
return 0;
|
|
|
|
ts->dsi = _free(ts->dsi);
|
2010-02-03 18:45:21 +08:00
|
|
|
ts->dsi = xcalloc(1, sizeof(*ts->dsi));
|
|
|
|
return 0;
|
|
|
|
}
|
2009-12-14 21:23:28 +08:00
|
|
|
|
2010-02-03 18:45:21 +08:00
|
|
|
static rpmDiskSpaceInfo rpmtsCreateDSI(const rpmts ts, dev_t dev,
|
|
|
|
const char * dirName, int count)
|
|
|
|
{
|
|
|
|
rpmDiskSpaceInfo dsi;
|
|
|
|
struct stat sb;
|
|
|
|
char * resolved_path;
|
|
|
|
char mntPoint[PATH_MAX];
|
|
|
|
int rc;
|
2009-12-14 21:23:28 +08:00
|
|
|
|
|
|
|
#if STATFS_IN_SYS_STATVFS
|
2010-02-03 18:45:21 +08:00
|
|
|
struct statvfs sfb;
|
|
|
|
memset(&sfb, 0, sizeof(sfb));
|
|
|
|
rc = statvfs(dirName, &sfb);
|
2009-12-14 21:23:28 +08:00
|
|
|
#else
|
2010-02-03 18:45:21 +08:00
|
|
|
struct statfs sfb;
|
|
|
|
memset(&sfb, 0, sizeof(sfb));
|
2009-12-14 21:23:28 +08:00
|
|
|
# if STAT_STATFS4
|
|
|
|
/* This platform has the 4-argument version of the statfs call. The last two
|
|
|
|
* should be the size of struct statfs and 0, respectively. The 0 is the
|
|
|
|
* filesystem type, and is always 0 when statfs is called on a mounted
|
|
|
|
* filesystem, as we're doing.
|
|
|
|
*/
|
2010-02-03 18:45:21 +08:00
|
|
|
rc = statfs(dirName, &sfb, sizeof(sfb), 0);
|
2009-12-14 21:23:28 +08:00
|
|
|
# else
|
2010-02-03 18:45:21 +08:00
|
|
|
rc = statfs(dirName, &sfb);
|
2009-12-14 21:23:28 +08:00
|
|
|
# endif
|
|
|
|
#endif
|
2010-02-03 18:45:21 +08:00
|
|
|
if (rc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
rc = stat(dirName, &sb);
|
|
|
|
if (rc)
|
|
|
|
return NULL;
|
2010-02-04 18:02:25 +08:00
|
|
|
if (sb.st_dev != dev)
|
2010-02-03 18:45:21 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ts->dsi = xrealloc(ts->dsi, (count + 2) * sizeof(*ts->dsi));
|
|
|
|
dsi = ts->dsi + count;
|
|
|
|
memset(dsi, 0, 2 * sizeof(*dsi));
|
|
|
|
|
|
|
|
dsi->dev = sb.st_dev;
|
|
|
|
dsi->bsize = sfb.f_bsize;
|
|
|
|
if (!dsi->bsize)
|
|
|
|
dsi->bsize = 512; /* we need a bsize */
|
|
|
|
dsi->bneeded = 0;
|
|
|
|
dsi->ineeded = 0;
|
2009-12-14 21:23:28 +08:00
|
|
|
#ifdef STATFS_HAS_F_BAVAIL
|
2010-02-03 18:45:21 +08:00
|
|
|
dsi->bavail = (sfb.f_flag & ST_RDONLY) ? 0 : sfb.f_bavail;
|
2009-12-14 21:23:28 +08:00
|
|
|
#else
|
|
|
|
/* FIXME: the statfs struct doesn't have a member to tell how many blocks are
|
|
|
|
* available for non-superusers. f_blocks - f_bfree is probably too big, but
|
|
|
|
* it's about all we can do.
|
|
|
|
*/
|
2010-02-03 18:45:21 +08:00
|
|
|
dsi->bavail = sfb.f_blocks - sfb.f_bfree;
|
2009-12-14 21:23:28 +08:00
|
|
|
#endif
|
2010-02-03 18:45:21 +08:00
|
|
|
/* XXX Avoid FAT and other file systems that have not inodes. */
|
|
|
|
/* XXX assigning negative value to unsigned type */
|
|
|
|
dsi->iavail = !(sfb.f_ffree == 0 && sfb.f_files == 0)
|
|
|
|
? sfb.f_ffree : -1;
|
|
|
|
|
|
|
|
/* Find mount point belonging to this device number */
|
|
|
|
resolved_path = realpath(dirName, mntPoint);
|
|
|
|
if (!resolved_path) {
|
|
|
|
strncpy(mntPoint, dirName, PATH_MAX);
|
2010-02-03 22:42:52 +08:00
|
|
|
mntPoint[PATH_MAX-1] = '\0';
|
2009-12-14 21:23:28 +08:00
|
|
|
}
|
2010-02-03 18:45:21 +08:00
|
|
|
char * end = NULL;
|
|
|
|
while (end != mntPoint) {
|
|
|
|
end = strrchr(mntPoint, '/');
|
2010-02-04 18:02:25 +08:00
|
|
|
if (end == mntPoint) { /* reached "/" */
|
2010-02-03 18:45:21 +08:00
|
|
|
stat("/", &sb);
|
|
|
|
if (dsi->dev != sb.st_dev) {
|
|
|
|
dsi->mntPoint = xstrdup(mntPoint);
|
|
|
|
} else {
|
|
|
|
dsi->mntPoint = xstrdup("/");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} else if (end) {
|
|
|
|
*end = '\0';
|
2010-02-04 18:02:25 +08:00
|
|
|
} else { /* dirName doesn't start with / - should not happen */
|
2010-02-03 18:45:21 +08:00
|
|
|
dsi->mntPoint = xstrdup(dirName);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
stat(mntPoint, &sb);
|
|
|
|
if (dsi->dev != sb.st_dev) {
|
|
|
|
*end = '/';
|
|
|
|
dsi->mntPoint = xstrdup(mntPoint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmlog(RPMLOG_DEBUG,
|
|
|
|
"0x%08x %8" PRId64 " %12" PRId64 " %12" PRId64" %s\n",
|
|
|
|
(unsigned) dsi->dev, dsi->bsize,
|
|
|
|
dsi->bavail, dsi->iavail,
|
|
|
|
dsi->mntPoint);
|
|
|
|
return dsi;
|
2009-12-14 21:23:28 +08:00
|
|
|
}
|
|
|
|
|
2010-02-02 18:25:59 +08:00
|
|
|
static rpmDiskSpaceInfo rpmtsGetDSI(const rpmts ts, dev_t dev,
|
|
|
|
const char *dirName) {
|
2009-12-14 21:23:28 +08:00
|
|
|
rpmDiskSpaceInfo dsi;
|
|
|
|
dsi = ts->dsi;
|
|
|
|
if (dsi) {
|
|
|
|
while (dsi->bsize && dsi->dev != dev)
|
|
|
|
dsi++;
|
2010-02-03 18:45:21 +08:00
|
|
|
if (dsi->bsize == 0) {
|
|
|
|
/* create new entry */
|
|
|
|
dsi = rpmtsCreateDSI(ts, dev, dirName, dsi - ts->dsi);
|
|
|
|
}
|
2009-12-14 21:23:28 +08:00
|
|
|
}
|
2010-02-02 18:25:59 +08:00
|
|
|
return dsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void rpmtsUpdateDSI(const rpmts ts, dev_t dev, const char *dirName,
|
|
|
|
rpm_loff_t fileSize, rpm_loff_t prevSize, rpm_loff_t fixupSize,
|
|
|
|
rpmFileAction action)
|
|
|
|
{
|
|
|
|
int64_t bneeded;
|
|
|
|
rpmDiskSpaceInfo dsi = rpmtsGetDSI(ts, dev, dirName);
|
2009-12-14 21:23:28 +08:00
|
|
|
if (dsi == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bneeded = BLOCK_ROUND(fileSize, dsi->bsize);
|
|
|
|
|
|
|
|
switch (action) {
|
|
|
|
case FA_BACKUP:
|
|
|
|
case FA_SAVE:
|
|
|
|
case FA_ALTNAME:
|
|
|
|
dsi->ineeded++;
|
|
|
|
dsi->bneeded += bneeded;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: If two packages share a file (same md5sum), and
|
|
|
|
* that file is being replaced on disk, will dsi->bneeded get
|
|
|
|
* adjusted twice? Quite probably!
|
|
|
|
*/
|
|
|
|
case FA_CREATE:
|
|
|
|
dsi->bneeded += bneeded;
|
|
|
|
dsi->bneeded -= BLOCK_ROUND(prevSize, dsi->bsize);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FA_ERASE:
|
|
|
|
dsi->ineeded--;
|
|
|
|
dsi->bneeded -= bneeded;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fixupSize)
|
|
|
|
dsi->bneeded -= BLOCK_ROUND(fixupSize, dsi->bsize);
|
2010-02-04 21:55:16 +08:00
|
|
|
|
|
|
|
/* adjust bookkeeping when requirements shrink */
|
|
|
|
if (dsi->bneeded < dsi->obneeded) dsi->obneeded = dsi->bneeded;
|
|
|
|
if (dsi->ineeded < dsi->oineeded) dsi->oineeded = dsi->ineeded;
|
2009-12-14 21:23:28 +08:00
|
|
|
}
|
|
|
|
|
2010-02-02 18:25:59 +08:00
|
|
|
/* return DSI of the device the rpmdb lives on */
|
2011-09-01 17:55:30 +08:00
|
|
|
static rpmDiskSpaceInfo rpmtsDbDSI(const rpmts ts)
|
|
|
|
{
|
2010-02-02 18:25:59 +08:00
|
|
|
const char *dbhome = rpmdbHome(rpmtsGetRdb(ts));
|
|
|
|
struct stat sb;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = stat(dbhome, &sb);
|
|
|
|
if (rc) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return rpmtsGetDSI(ts, sb.st_dev, dbhome);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update DSI for changing size of the rpmdb */
|
2011-09-01 17:55:30 +08:00
|
|
|
static void rpmtsUpdateDSIrpmDBSize(const rpmte p, rpmDiskSpaceInfo dsi)
|
|
|
|
{
|
2010-02-02 18:25:59 +08:00
|
|
|
rpm_loff_t headerSize;
|
|
|
|
int64_t bneeded;
|
|
|
|
|
2011-01-21 20:02:28 +08:00
|
|
|
/* XXX somehow we can end up here with bsize 0 (RhBug:671056) */
|
|
|
|
if (dsi == NULL || dsi->bsize == 0) return;
|
2010-02-02 18:25:59 +08:00
|
|
|
|
|
|
|
headerSize = rpmteHeaderSize(p);
|
|
|
|
bneeded = BLOCK_ROUND(headerSize, dsi->bsize);
|
|
|
|
/* REMOVE doesn't neccessarily shrink the database */
|
|
|
|
if (rpmteType(p) == TR_ADDED) {
|
|
|
|
/* guessing that db grows 4 times more than the header size */
|
|
|
|
dsi->bneeded += (bneeded * 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-14 21:23:28 +08:00
|
|
|
static void rpmtsCheckDSIProblems(const rpmts ts, const rpmte te)
|
|
|
|
{
|
2010-02-26 19:45:47 +08:00
|
|
|
rpmDiskSpaceInfo dsi = ts->dsi;
|
2009-12-14 21:23:28 +08:00
|
|
|
|
2010-02-03 18:45:21 +08:00
|
|
|
if (dsi == NULL || !dsi->bsize)
|
2009-12-14 21:23:28 +08:00
|
|
|
return;
|
2010-02-26 19:45:47 +08:00
|
|
|
if (rpmfiFC(rpmteFI(te)) <= 0)
|
2009-12-14 21:23:28 +08:00
|
|
|
return;
|
|
|
|
|
2010-02-03 18:45:21 +08:00
|
|
|
for (; dsi->bsize; dsi++) {
|
2009-12-14 21:23:28 +08:00
|
|
|
|
|
|
|
if (dsi->bavail >= 0 && adj_fs_blocks(dsi->bneeded) > dsi->bavail) {
|
2010-02-04 21:55:16 +08:00
|
|
|
if (dsi->bneeded > dsi->obneeded) {
|
2010-03-26 21:28:25 +08:00
|
|
|
rpmteAddProblem(te, RPMPROB_DISKSPACE, NULL, dsi->mntPoint,
|
2009-12-14 21:23:28 +08:00
|
|
|
(adj_fs_blocks(dsi->bneeded) - dsi->bavail) * dsi->bsize);
|
|
|
|
dsi->obneeded = dsi->bneeded;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dsi->iavail >= 0 && adj_fs_blocks(dsi->ineeded) > dsi->iavail) {
|
2010-02-04 21:55:16 +08:00
|
|
|
if (dsi->ineeded > dsi->oineeded) {
|
2010-03-26 21:28:25 +08:00
|
|
|
rpmteAddProblem(te, RPMPROB_DISKNODES, NULL, dsi->mntPoint,
|
2009-12-14 21:23:28 +08:00
|
|
|
(adj_fs_blocks(dsi->ineeded) - dsi->iavail));
|
|
|
|
dsi->oineeded = dsi->ineeded;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-03-06 02:22:25 +08:00
|
|
|
|
2011-09-01 17:55:30 +08:00
|
|
|
static void rpmtsFreeDSI(rpmts ts)
|
|
|
|
{
|
2010-02-03 18:45:21 +08:00
|
|
|
rpmDiskSpaceInfo dsi;
|
|
|
|
if (ts == NULL)
|
|
|
|
return;
|
|
|
|
dsi = ts->dsi;
|
|
|
|
while (dsi && dsi->bsize != 0) {
|
|
|
|
dsi->mntPoint = _free(dsi->mntPoint);
|
|
|
|
dsi++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ts->dsi = _free(ts->dsi);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-24 15:21:20 +08:00
|
|
|
/* Calculate total number of files involved in transaction */
|
|
|
|
static uint64_t countFiles(rpmts ts)
|
|
|
|
{
|
|
|
|
uint64_t fc = 0;
|
|
|
|
rpmtsi pi = rpmtsiInit(ts);
|
|
|
|
rpmte p;
|
2010-02-26 02:52:35 +08:00
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL)
|
|
|
|
fc += rpmfiFC(rpmteFI(p));
|
2011-05-29 03:29:58 +08:00
|
|
|
rpmtsiFree(pi);
|
2009-02-24 15:21:20 +08:00
|
|
|
return fc;
|
|
|
|
}
|
|
|
|
|
2001-09-26 04:51:34 +08:00
|
|
|
/**
|
2007-10-06 10:41:49 +08:00
|
|
|
* handleInstInstalledFiles.
|
2003-07-10 04:18:54 +08:00
|
|
|
* @param ts transaction set
|
2007-10-06 10:41:49 +08:00
|
|
|
* @param p current transaction element
|
2003-07-10 04:18:54 +08:00
|
|
|
* @param fi file info set
|
2007-10-06 10:41:49 +08:00
|
|
|
* @param shared shared file info
|
|
|
|
* @param sharedCount no. of shared elements
|
2003-07-10 04:18:54 +08:00
|
|
|
* @param reportConflicts
|
2001-09-26 04:51:34 +08:00
|
|
|
*/
|
2001-10-19 09:24:21 +08:00
|
|
|
/* XXX only ts->{probs,rpmdb} modified */
|
2011-03-04 19:46:06 +08:00
|
|
|
static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfi fi,
|
2008-11-07 17:58:25 +08:00
|
|
|
Header otherHeader, rpmfi otherFi,
|
|
|
|
int beingRemoved)
|
1999-07-14 22:36:10 +08:00
|
|
|
{
|
2008-12-03 17:39:48 +08:00
|
|
|
unsigned int fx = rpmfiFX(fi);
|
|
|
|
rpmfs fs = rpmteGetFileStates(p);
|
2009-03-08 23:38:49 +08:00
|
|
|
int isCfgFile = ((rpmfiFFlags(otherFi) | rpmfiFFlags(fi)) & RPMFILE_CONFIG);
|
2002-07-28 08:41:15 +08:00
|
|
|
|
2008-12-03 17:39:48 +08:00
|
|
|
if (XFA_SKIPPING(rpmfsGetAction(fs, fx)))
|
2011-03-04 19:46:06 +08:00
|
|
|
return;
|
2008-11-07 17:58:25 +08:00
|
|
|
|
|
|
|
if (rpmfiCompare(otherFi, fi)) {
|
2009-03-08 23:36:39 +08:00
|
|
|
rpm_color_t tscolor = rpmtsColor(ts);
|
|
|
|
rpm_color_t prefcolor = rpmtsPrefColor(ts);
|
|
|
|
rpm_color_t FColor = rpmfiFColor(fi) & tscolor;
|
|
|
|
rpm_color_t oFColor = rpmfiFColor(otherFi) & tscolor;
|
2008-11-07 17:58:25 +08:00
|
|
|
int rConflicts;
|
2011-08-29 19:04:28 +08:00
|
|
|
char rState = RPMFILE_STATE_REPLACED;
|
2008-11-07 17:58:25 +08:00
|
|
|
|
|
|
|
rConflicts = !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES));
|
|
|
|
/* Resolve file conflicts to prefer Elf64 (if not forced). */
|
2011-05-26 16:40:55 +08:00
|
|
|
if (tscolor != 0 && FColor != 0 && oFColor != 0 && FColor != oFColor) {
|
2008-11-07 17:58:25 +08:00
|
|
|
if (oFColor & prefcolor) {
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, fx, FA_SKIPCOLOR);
|
2008-11-07 17:58:25 +08:00
|
|
|
rConflicts = 0;
|
|
|
|
} else if (FColor & prefcolor) {
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, fx, FA_CREATE);
|
2008-11-07 17:58:25 +08:00
|
|
|
rConflicts = 0;
|
2011-08-29 19:04:28 +08:00
|
|
|
rState = RPMFILE_STATE_WRONGCOLOR;
|
2003-07-10 04:18:54 +08:00
|
|
|
}
|
2008-11-07 17:58:25 +08:00
|
|
|
}
|
2003-07-10 04:18:54 +08:00
|
|
|
|
2008-11-07 17:58:25 +08:00
|
|
|
if (rConflicts) {
|
2009-09-02 17:06:34 +08:00
|
|
|
char *altNEVR = headerGetAsString(otherHeader, RPMTAG_NEVRA);
|
2010-03-26 21:22:13 +08:00
|
|
|
rpmteAddProblem(p, RPMPROB_FILE_CONFLICT, altNEVR, rpmfiFN(fi),
|
|
|
|
headerGetInstance(otherHeader));
|
2009-03-08 23:25:45 +08:00
|
|
|
free(altNEVR);
|
1999-08-14 04:05:57 +08:00
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2008-11-07 17:58:25 +08:00
|
|
|
/* Save file identifier to mark as state REPLACED. */
|
2008-12-03 17:39:48 +08:00
|
|
|
if ( !(isCfgFile || XFA_SKIPPING(rpmfsGetAction(fs, fx))) ) {
|
2008-11-07 17:58:25 +08:00
|
|
|
if (!beingRemoved)
|
2011-08-29 19:04:28 +08:00
|
|
|
rpmfsAddReplaced(rpmteGetFileStates(p), rpmfiFX(fi), rState,
|
2008-11-07 17:58:25 +08:00
|
|
|
headerGetInstance(otherHeader),
|
|
|
|
rpmfiFX(otherFi));
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-07 17:58:25 +08:00
|
|
|
/* Determine config file dispostion, skipping missing files (if any). */
|
|
|
|
if (isCfgFile) {
|
2009-03-08 23:38:49 +08:00
|
|
|
int skipMissing = ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1);
|
2008-11-07 17:58:25 +08:00
|
|
|
rpmFileAction action = rpmfiDecideFate(otherFi, fi, skipMissing);
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, fx, action);
|
2008-11-07 17:58:25 +08:00
|
|
|
}
|
|
|
|
rpmfiSetFReplacedSize(fi, rpmfiFSize(otherFi));
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
|
|
|
|
2000-10-21 00:47:00 +08:00
|
|
|
/**
|
2002-05-20 02:42:25 +08:00
|
|
|
* Update disk space needs on each partition for this package's files.
|
2000-10-21 00:47:00 +08:00
|
|
|
*/
|
2001-10-19 09:24:21 +08:00
|
|
|
/* XXX only ts->{probs,di} modified */
|
2009-02-24 17:23:25 +08:00
|
|
|
static void handleOverlappedFiles(rpmts ts, rpmFpHash ht, rpmte p, rpmfi fi)
|
1999-07-14 22:36:10 +08:00
|
|
|
{
|
2008-06-12 21:41:31 +08:00
|
|
|
rpm_loff_t fixupSize = 0;
|
2001-11-14 08:14:01 +08:00
|
|
|
const char * fn;
|
2001-10-19 00:39:54 +08:00
|
|
|
int i, j;
|
2008-11-13 15:56:52 +08:00
|
|
|
rpm_color_t tscolor = rpmtsColor(ts);
|
|
|
|
rpm_color_t prefcolor = rpmtsPrefColor(ts);
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfs fs = rpmteGetFileStates(p);
|
|
|
|
rpmfs otherFs;
|
2004-03-27 01:27:57 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
fi = rpmfiInit(fi, 0);
|
|
|
|
while ((i = rpmfiNext(fi)) >= 0) {
|
2008-02-05 18:12:31 +08:00
|
|
|
rpm_color_t oFColor, FColor;
|
2001-11-16 02:22:33 +08:00
|
|
|
struct fingerPrint_s * fiFps;
|
1999-08-15 04:01:38 +08:00
|
|
|
int otherPkgNum, otherFileNum;
|
2002-05-20 02:42:25 +08:00
|
|
|
rpmfi otherFi;
|
2008-11-27 16:22:45 +08:00
|
|
|
rpmte otherTe;
|
2008-02-05 21:15:41 +08:00
|
|
|
rpmfileAttrs FFlags;
|
2008-02-05 18:31:32 +08:00
|
|
|
rpm_mode_t FMode;
|
2008-10-21 21:45:09 +08:00
|
|
|
struct rpmffi_s * recs;
|
1999-08-15 04:01:38 +08:00
|
|
|
int numRecs;
|
|
|
|
|
2008-12-03 17:39:48 +08:00
|
|
|
if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
|
1999-07-14 22:36:10 +08:00
|
|
|
continue;
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
fn = rpmfiFN(fi);
|
2008-12-19 21:04:51 +08:00
|
|
|
fiFps = rpmfiFpsIndex(fi, i);
|
2002-07-28 08:41:15 +08:00
|
|
|
FFlags = rpmfiFFlags(fi);
|
|
|
|
FMode = rpmfiFMode(fi);
|
2003-07-10 04:18:54 +08:00
|
|
|
FColor = rpmfiFColor(fi);
|
|
|
|
FColor &= tscolor;
|
1999-10-20 18:22:46 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
fixupSize = 0;
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-08-18 07:05:24 +08:00
|
|
|
/*
|
|
|
|
* Retrieve all records that apply to this file. Note that the
|
|
|
|
* file info records were built in the same order as the packages
|
|
|
|
* will be installed and removed so the records for an overlapped
|
|
|
|
* files will be sorted in exactly the same order.
|
|
|
|
*/
|
2009-02-24 17:23:25 +08:00
|
|
|
(void) rpmFpHashGetEntry(ht, fiFps, &recs, &numRecs, NULL);
|
1999-08-18 07:05:24 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If this package is being added, look only at other packages
|
|
|
|
* being added -- removed packages dance to a different tune.
|
2002-05-20 02:42:25 +08:00
|
|
|
*
|
1999-08-18 07:05:24 +08:00
|
|
|
* If both this and the other package are being added, overlapped
|
|
|
|
* files must be identical (or marked as a conflict). The
|
|
|
|
* disposition of already installed config files leads to
|
|
|
|
* a small amount of extra complexity.
|
|
|
|
*
|
|
|
|
* If this package is being removed, then there are two cases that
|
|
|
|
* need to be worried about:
|
|
|
|
* If the other package is being added, then skip any overlapped files
|
|
|
|
* so that this package removal doesn't nuke the overlapped files
|
|
|
|
* that were just installed.
|
|
|
|
* If both this and the other package are being removed, then each
|
|
|
|
* file removal from preceding packages needs to be skipped so that
|
|
|
|
* the file removal occurs only on the last occurence of an overlapped
|
|
|
|
* file in the transaction set.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Locate this overlapped file in the set of added/removed packages. */
|
2008-11-26 23:29:55 +08:00
|
|
|
for (j = 0; j < numRecs && recs[j].p != p; j++)
|
2001-06-06 03:26:22 +08:00
|
|
|
{};
|
1999-07-14 22:36:10 +08:00
|
|
|
|
1999-08-18 07:05:24 +08:00
|
|
|
/* Find what the previous disposition of this file was. */
|
1999-07-14 22:36:10 +08:00
|
|
|
otherFileNum = -1; /* keep gcc quiet */
|
2001-11-17 03:26:33 +08:00
|
|
|
otherFi = NULL;
|
2008-11-27 16:22:45 +08:00
|
|
|
otherTe = NULL;
|
2008-12-03 17:39:48 +08:00
|
|
|
otherFs = NULL;
|
2008-10-21 21:45:09 +08:00
|
|
|
|
1999-08-14 04:05:57 +08:00
|
|
|
for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
|
2008-11-27 16:22:45 +08:00
|
|
|
otherTe = recs[otherPkgNum].p;
|
|
|
|
otherFi = rpmteFI(otherTe);
|
2008-10-21 21:45:09 +08:00
|
|
|
otherFileNum = recs[otherPkgNum].fileno;
|
2008-12-03 17:39:48 +08:00
|
|
|
otherFs = rpmteGetFileStates(otherTe);
|
2001-11-16 02:22:33 +08:00
|
|
|
|
1999-08-18 07:05:24 +08:00
|
|
|
/* Added packages need only look at other added packages. */
|
2008-11-27 16:22:45 +08:00
|
|
|
if (rpmteType(p) == TR_ADDED && rpmteType(otherTe) != TR_ADDED)
|
2007-09-12 01:07:39 +08:00
|
|
|
continue;
|
1999-08-14 04:05:57 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
(void) rpmfiSetFX(otherFi, otherFileNum);
|
2000-06-17 03:12:09 +08:00
|
|
|
|
2002-06-22 02:00:50 +08:00
|
|
|
/* XXX Happens iff fingerprint for incomplete package install. */
|
2009-09-07 19:15:56 +08:00
|
|
|
if (rpmfsGetAction(otherFs, otherFileNum) != FA_UNKNOWN)
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
1998-12-19 03:09:38 +08:00
|
|
|
}
|
|
|
|
|
2003-07-10 04:18:54 +08:00
|
|
|
oFColor = rpmfiFColor(otherFi);
|
|
|
|
oFColor &= tscolor;
|
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
switch (rpmteType(p)) {
|
1999-08-14 04:05:57 +08:00
|
|
|
case TR_ADDED:
|
2007-08-09 20:15:24 +08:00
|
|
|
{
|
2003-07-10 04:18:54 +08:00
|
|
|
int reportConflicts =
|
|
|
|
!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
|
|
|
|
int done = 0;
|
|
|
|
|
1999-08-15 04:01:38 +08:00
|
|
|
if (otherPkgNum < 0) {
|
1999-08-18 07:05:24 +08:00
|
|
|
/* XXX is this test still necessary? */
|
2008-11-12 04:32:23 +08:00
|
|
|
rpmFileAction action;
|
2008-12-03 17:39:48 +08:00
|
|
|
if (rpmfsGetAction(fs, i) != FA_UNKNOWN)
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2007-08-09 20:15:24 +08:00
|
|
|
if (rpmfiConfigConflict(fi)) {
|
1999-08-18 07:05:24 +08:00
|
|
|
/* Here is a non-overlapped pre-existing config file. */
|
2008-11-12 04:32:23 +08:00
|
|
|
action = (FFlags & RPMFILE_NOREPLACE) ?
|
|
|
|
FA_ALTNAME : FA_BACKUP;
|
1999-08-17 06:10:27 +08:00
|
|
|
} else {
|
2008-11-12 04:32:23 +08:00
|
|
|
action = FA_CREATE;
|
1999-08-17 06:10:27 +08:00
|
|
|
}
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, action);
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
1999-08-17 06:10:27 +08:00
|
|
|
|
2001-11-16 08:26:30 +08:00
|
|
|
assert(otherFi != NULL);
|
2000-10-21 00:47:00 +08:00
|
|
|
/* Mark added overlapped non-identical files as a conflict. */
|
2003-07-10 04:18:54 +08:00
|
|
|
if (rpmfiCompare(otherFi, fi)) {
|
2004-07-05 23:24:17 +08:00
|
|
|
int rConflicts;
|
2003-07-10 04:18:54 +08:00
|
|
|
|
2004-07-05 23:24:17 +08:00
|
|
|
rConflicts = reportConflicts;
|
2003-07-10 04:18:54 +08:00
|
|
|
/* Resolve file conflicts to prefer Elf64 (if not forced) ... */
|
2011-05-26 19:16:14 +08:00
|
|
|
if (tscolor != 0 && FColor != 0 && oFColor != 0 && FColor != oFColor) {
|
2007-05-01 12:55:14 +08:00
|
|
|
if (FColor & prefcolor) {
|
|
|
|
/* ... last file of preferred colour is installed ... */
|
2009-06-15 20:21:27 +08:00
|
|
|
if (!XFA_SKIPPING(rpmfsGetAction(fs, i)))
|
|
|
|
rpmfsSetAction(otherFs, otherFileNum, FA_SKIPCOLOR);
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_CREATE);
|
2004-07-05 23:24:17 +08:00
|
|
|
rConflicts = 0;
|
2003-07-10 04:18:54 +08:00
|
|
|
} else
|
2007-05-01 12:55:14 +08:00
|
|
|
if (oFColor & prefcolor) {
|
|
|
|
/* ... first file of preferred colour is installed ... */
|
2008-12-03 17:39:48 +08:00
|
|
|
if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
|
|
|
|
rpmfsSetAction(otherFs, otherFileNum, FA_CREATE);
|
|
|
|
rpmfsSetAction(fs, i, FA_SKIPCOLOR);
|
2004-07-05 23:24:17 +08:00
|
|
|
rConflicts = 0;
|
2003-07-10 04:18:54 +08:00
|
|
|
}
|
|
|
|
done = 1;
|
|
|
|
}
|
2004-07-05 23:24:17 +08:00
|
|
|
if (rConflicts) {
|
2010-03-13 01:41:10 +08:00
|
|
|
rpmteAddProblem(p, RPMPROB_NEW_FILE_CONFLICT,
|
2010-03-26 16:27:39 +08:00
|
|
|
rpmteNEVRA(otherTe), fn, 0);
|
2003-07-10 04:18:54 +08:00
|
|
|
}
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
|
1999-08-18 07:05:24 +08:00
|
|
|
/* Try to get the disk accounting correct even if a conflict. */
|
2002-07-28 08:41:15 +08:00
|
|
|
fixupSize = rpmfiFSize(otherFi);
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2007-08-09 20:15:24 +08:00
|
|
|
if (rpmfiConfigConflict(fi)) {
|
1999-08-18 07:05:24 +08:00
|
|
|
/* Here is an overlapped pre-existing config file. */
|
2008-11-12 04:32:23 +08:00
|
|
|
rpmFileAction action;
|
|
|
|
action = (FFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SKIP;
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, action);
|
1999-08-17 06:10:27 +08:00
|
|
|
} else {
|
2003-07-10 04:18:54 +08:00
|
|
|
if (!done)
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_CREATE);
|
1999-08-17 06:10:27 +08:00
|
|
|
}
|
2007-09-12 01:07:39 +08:00
|
|
|
} break;
|
2001-11-16 02:22:33 +08:00
|
|
|
|
1999-08-14 04:05:57 +08:00
|
|
|
case TR_REMOVED:
|
1999-08-15 04:01:38 +08:00
|
|
|
if (otherPkgNum >= 0) {
|
2008-12-03 17:39:48 +08:00
|
|
|
assert(otherFi != NULL);
|
|
|
|
/* Here is an overlapped added file we don't want to nuke. */
|
|
|
|
if (rpmfsGetAction(otherFs, otherFileNum) != FA_ERASE) {
|
1999-08-17 06:10:27 +08:00
|
|
|
/* On updates, don't remove files. */
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_SKIP);
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
1999-08-15 21:41:06 +08:00
|
|
|
}
|
1999-08-18 07:05:24 +08:00
|
|
|
/* Here is an overlapped removed file: skip in previous. */
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(otherFs, otherFileNum, FA_SKIP);
|
1999-08-15 04:01:38 +08:00
|
|
|
}
|
2008-12-03 17:39:48 +08:00
|
|
|
if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-07-28 08:41:15 +08:00
|
|
|
if (rpmfiFState(fi) != RPMFILE_STATE_NORMAL)
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2002-07-28 08:41:15 +08:00
|
|
|
if (!(S_ISREG(FMode) && (FFlags & RPMFILE_CONFIG))) {
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_ERASE);
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
1999-08-15 04:01:38 +08:00
|
|
|
}
|
|
|
|
|
1999-08-18 07:05:24 +08:00
|
|
|
/* Here is a pre-existing modified config file that needs saving. */
|
2010-10-22 17:58:09 +08:00
|
|
|
{ int algo = 0;
|
2008-05-29 20:48:40 +08:00
|
|
|
size_t diglen = 0;
|
|
|
|
const unsigned char *digest;
|
2008-05-30 17:06:40 +08:00
|
|
|
if ((digest = rpmfiFDigest(fi, &algo, &diglen))) {
|
2008-05-29 20:48:40 +08:00
|
|
|
unsigned char fdigest[diglen];
|
|
|
|
if (!rpmDoDigest(algo, fn, 0, fdigest, NULL) &&
|
|
|
|
memcmp(digest, fdigest, diglen)) {
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_BACKUP);
|
2008-05-29 20:48:40 +08:00
|
|
|
break;
|
|
|
|
}
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
1999-01-19 11:01:52 +08:00
|
|
|
}
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_ERASE);
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
/* Update disk space info for a file. */
|
2010-02-03 18:45:21 +08:00
|
|
|
rpmtsUpdateDSI(ts, fiFps->entry->dev, fiFps->entry->dirName,
|
|
|
|
rpmfiFSize(fi), rpmfiFReplacedSize(fi),
|
|
|
|
fixupSize, rpmfsGetAction(fs, i));
|
1998-12-19 03:09:38 +08:00
|
|
|
|
|
|
|
}
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2001-09-26 04:51:34 +08:00
|
|
|
/**
|
2001-11-11 03:24:19 +08:00
|
|
|
* Ensure that current package is newer than installed package.
|
|
|
|
* @param p current transaction element
|
|
|
|
* @param h installed header
|
2009-02-24 16:13:43 +08:00
|
|
|
* @param ps problem set
|
2001-09-26 04:51:34 +08:00
|
|
|
*/
|
2010-03-13 01:41:10 +08:00
|
|
|
static void ensureOlder(const rpmte p, const Header h)
|
2001-11-11 03:24:19 +08:00
|
|
|
{
|
2008-01-30 22:04:40 +08:00
|
|
|
rpmsenseFlags reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL);
|
2002-05-20 02:42:25 +08:00
|
|
|
rpmds req;
|
2001-11-11 03:24:19 +08:00
|
|
|
|
2008-04-24 19:56:27 +08:00
|
|
|
req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), rpmteEVR(p), reqFlags);
|
2010-02-26 03:50:20 +08:00
|
|
|
if (rpmdsNVRMatchesDep(h, req, _rpmds_nopromote) == 0) {
|
2009-09-02 17:06:34 +08:00
|
|
|
char * altNEVR = headerGetAsString(h, RPMTAG_NEVRA);
|
2010-03-26 21:22:13 +08:00
|
|
|
rpmteAddProblem(p, RPMPROB_OLDPACKAGE, altNEVR, NULL,
|
|
|
|
headerGetInstance(h));
|
2010-02-26 03:50:20 +08:00
|
|
|
free(altNEVR);
|
|
|
|
}
|
|
|
|
rpmdsFree(req);
|
2001-11-11 03:24:19 +08:00
|
|
|
}
|
1999-01-01 03:16:31 +08:00
|
|
|
|
2009-09-14 22:19:33 +08:00
|
|
|
/**
|
|
|
|
* Check if the curent file in the file iterator is in the
|
|
|
|
* netshardpath and though should be excluded.
|
|
|
|
* @param ts transaction set
|
|
|
|
* @param fi file info set
|
|
|
|
* @returns pointer to matching path or NULL
|
|
|
|
*/
|
|
|
|
static char ** matchNetsharedpath(const rpmts ts, rpmfi fi)
|
|
|
|
{
|
|
|
|
char ** nsp;
|
|
|
|
const char * dn, * bn;
|
|
|
|
size_t dnlen, bnlen;
|
|
|
|
char * s;
|
|
|
|
bn = rpmfiBN(fi);
|
|
|
|
bnlen = strlen(bn);
|
|
|
|
dn = rpmfiDN(fi);
|
|
|
|
dnlen = strlen(dn);
|
|
|
|
for (nsp = ts->netsharedPaths; nsp && *nsp; nsp++) {
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
len = strlen(*nsp);
|
|
|
|
if (dnlen >= len) {
|
|
|
|
if (!rstreqn(dn, *nsp, len))
|
|
|
|
continue;
|
|
|
|
/* Only directories or complete file paths can be net shared */
|
|
|
|
if (!(dn[len] == '/' || dn[len] == '\0'))
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (len < (dnlen + bnlen))
|
|
|
|
continue;
|
|
|
|
if (!rstreqn(dn, *nsp, dnlen))
|
|
|
|
continue;
|
|
|
|
/* Insure that only the netsharedpath basename is compared. */
|
|
|
|
if ((s = strchr((*nsp) + dnlen, '/')) != NULL && s[1] != '\0')
|
|
|
|
continue;
|
|
|
|
if (!rstreqn(bn, (*nsp) + dnlen, bnlen))
|
|
|
|
continue;
|
|
|
|
len = dnlen + bnlen;
|
|
|
|
/* Only directories or complete file paths can be net shared */
|
|
|
|
if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0'))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return nsp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void skipEraseFiles(const rpmts ts, rpmte p)
|
|
|
|
{
|
|
|
|
rpmfi fi = rpmteFI(p);
|
|
|
|
rpmfs fs = rpmteGetFileStates(p);
|
|
|
|
int i;
|
|
|
|
char ** nsp;
|
|
|
|
/*
|
|
|
|
* Skip net shared paths.
|
|
|
|
* Net shared paths are not relative to the current root (though
|
|
|
|
* they do need to take package relocations into account).
|
|
|
|
*/
|
|
|
|
fi = rpmfiInit(fi, 0);
|
|
|
|
while ((i = rpmfiNext(fi)) >= 0)
|
|
|
|
{
|
|
|
|
nsp = matchNetsharedpath(ts, fi);
|
|
|
|
if (nsp && *nsp) {
|
|
|
|
rpmfsSetAction(fs, i, FA_SKIPNETSHARED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-09-26 04:51:34 +08:00
|
|
|
/**
|
2002-12-25 01:06:35 +08:00
|
|
|
* Skip any files that do not match install policies.
|
|
|
|
* @param ts transaction set
|
|
|
|
* @param fi file info set
|
2001-09-26 04:51:34 +08:00
|
|
|
*/
|
2009-09-14 22:19:33 +08:00
|
|
|
static void skipInstallFiles(const rpmts ts, rpmte p)
|
1999-07-14 22:36:10 +08:00
|
|
|
{
|
2008-02-05 18:12:31 +08:00
|
|
|
rpm_color_t tscolor = rpmtsColor(ts);
|
|
|
|
rpm_color_t FColor;
|
2002-12-25 01:06:35 +08:00
|
|
|
int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS);
|
2002-05-20 07:37:24 +08:00
|
|
|
int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS);
|
2001-04-03 21:41:56 +08:00
|
|
|
int * drc;
|
|
|
|
char * dff;
|
2001-11-16 08:26:30 +08:00
|
|
|
int dc;
|
2007-12-14 17:38:20 +08:00
|
|
|
int i, j, ix;
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfi fi = rpmteFI(p);
|
|
|
|
rpmfs fs = rpmteGetFileStates(p);
|
1999-01-01 03:16:31 +08:00
|
|
|
|
1999-07-14 22:36:10 +08:00
|
|
|
if (!noDocs)
|
|
|
|
noDocs = rpmExpandNumeric("%{_excludedocs}");
|
1999-01-01 03:16:31 +08:00
|
|
|
|
2001-04-03 21:41:56 +08:00
|
|
|
/* Compute directory refcount, skip directory if now empty. */
|
2002-05-20 02:42:25 +08:00
|
|
|
dc = rpmfiDC(fi);
|
2008-04-25 19:34:36 +08:00
|
|
|
drc = xcalloc(dc, sizeof(*drc));
|
|
|
|
dff = xcalloc(dc, sizeof(*dff));
|
2001-11-16 08:26:30 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
fi = rpmfiInit(fi, 0);
|
2010-11-04 20:09:33 +08:00
|
|
|
while ((i = rpmfiNext(fi)) >= 0) {
|
2002-12-31 09:23:03 +08:00
|
|
|
char ** nsp;
|
2008-11-20 15:40:46 +08:00
|
|
|
const char *flangs;
|
1999-08-07 08:07:51 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
ix = rpmfiDX(fi);
|
2001-04-04 04:41:09 +08:00
|
|
|
drc[ix]++;
|
2001-04-03 21:41:56 +08:00
|
|
|
|
1999-08-07 08:07:51 +08:00
|
|
|
/* Don't bother with skipped files */
|
2008-12-03 17:39:48 +08:00
|
|
|
if (XFA_SKIPPING(rpmfsGetAction(fs, i))) {
|
2003-01-02 01:26:46 +08:00
|
|
|
drc[ix]--; dff[ix] = 1;
|
1999-07-14 22:36:10 +08:00
|
|
|
continue;
|
2001-04-03 21:41:56 +08:00
|
|
|
}
|
1999-01-01 03:16:31 +08:00
|
|
|
|
2002-12-31 09:23:03 +08:00
|
|
|
/* Ignore colored files not in our rainbow. */
|
2003-07-10 04:18:54 +08:00
|
|
|
FColor = rpmfiFColor(fi);
|
|
|
|
if (tscolor && FColor && !(tscolor & FColor)) {
|
2002-12-31 09:23:03 +08:00
|
|
|
drc[ix]--; dff[ix] = 1;
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_SKIPCOLOR);
|
2003-01-02 01:26:46 +08:00
|
|
|
continue;
|
2002-12-31 09:23:03 +08:00
|
|
|
}
|
|
|
|
|
1999-08-07 08:07:51 +08:00
|
|
|
/*
|
|
|
|
* Skip net shared paths.
|
|
|
|
* Net shared paths are not relative to the current root (though
|
|
|
|
* they do need to take package relocations into account).
|
|
|
|
*/
|
2009-09-14 22:19:33 +08:00
|
|
|
nsp = matchNetsharedpath(ts, fi);
|
1999-07-14 22:36:10 +08:00
|
|
|
if (nsp && *nsp) {
|
2001-04-04 04:41:09 +08:00
|
|
|
drc[ix]--; dff[ix] = 1;
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_SKIPNETSHARED);
|
1999-07-14 22:36:10 +08:00
|
|
|
continue;
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
|
1999-08-07 08:07:51 +08:00
|
|
|
/*
|
|
|
|
* Skip i18n language specific files.
|
|
|
|
*/
|
2009-03-09 20:57:46 +08:00
|
|
|
flangs = (ts->installLangs != NULL) ? rpmfiFLangs(fi) : NULL;
|
|
|
|
if (flangs != NULL && *flangs != '\0') {
|
2007-12-19 20:13:34 +08:00
|
|
|
const char *l, *le;
|
|
|
|
char **lang;
|
2008-11-30 20:07:03 +08:00
|
|
|
for (lang = ts->installLangs; *lang != NULL; lang++) {
|
2008-11-20 15:40:46 +08:00
|
|
|
for (l = flangs; *l != '\0'; l = le) {
|
2001-04-29 09:05:43 +08:00
|
|
|
for (le = l; *le != '\0' && *le != '|'; le++)
|
2001-06-06 03:26:22 +08:00
|
|
|
{};
|
2009-08-31 18:03:53 +08:00
|
|
|
if ((le-l) > 0 && rstreqn(*lang, l, (le-l)))
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
1999-07-14 22:36:10 +08:00
|
|
|
if (*le == '|') le++; /* skip over | */
|
|
|
|
}
|
2001-06-06 03:26:22 +08:00
|
|
|
if (*l != '\0')
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
1999-08-07 08:07:51 +08:00
|
|
|
if (*lang == NULL) {
|
2001-04-04 04:41:09 +08:00
|
|
|
drc[ix]--; dff[ix] = 1;
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_SKIPNSTATE);
|
1999-07-14 22:36:10 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
1999-01-01 03:16:31 +08:00
|
|
|
|
2002-12-25 01:06:35 +08:00
|
|
|
/*
|
|
|
|
* Skip config files if requested.
|
|
|
|
*/
|
|
|
|
if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) {
|
|
|
|
drc[ix]--; dff[ix] = 1;
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_SKIPNSTATE);
|
2002-12-25 01:06:35 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
1999-08-07 08:07:51 +08:00
|
|
|
/*
|
|
|
|
* Skip documentation if requested.
|
|
|
|
*/
|
2002-05-20 02:42:25 +08:00
|
|
|
if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) {
|
2001-04-04 04:41:09 +08:00
|
|
|
drc[ix]--; dff[ix] = 1;
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_SKIPNSTATE);
|
2001-04-21 14:02:09 +08:00
|
|
|
continue;
|
2001-04-03 21:41:56 +08:00
|
|
|
}
|
1999-01-01 03:16:31 +08:00
|
|
|
}
|
|
|
|
|
2001-04-03 21:41:56 +08:00
|
|
|
/* Skip (now empty) directories that had skipped files. */
|
2010-11-04 19:49:07 +08:00
|
|
|
for (j = 0; j < dc; j++) {
|
2010-11-04 20:09:33 +08:00
|
|
|
const char * dn, * bn;
|
|
|
|
size_t dnlen, bnlen;
|
2001-04-03 21:41:56 +08:00
|
|
|
|
|
|
|
if (drc[j]) continue; /* dir still has files. */
|
|
|
|
if (!dff[j]) continue; /* dir was not emptied here. */
|
|
|
|
|
|
|
|
/* Find parent directory and basename. */
|
2008-12-19 21:05:54 +08:00
|
|
|
dn = rpmfiDNIndex(fi, j); dnlen = strlen(dn) - 1;
|
2001-04-03 21:41:56 +08:00
|
|
|
bn = dn + dnlen; bnlen = 0;
|
|
|
|
while (bn > dn && bn[-1] != '/') {
|
|
|
|
bnlen++;
|
|
|
|
dnlen--;
|
|
|
|
bn--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If explicitly included in the package, skip the directory. */
|
2002-05-20 02:42:25 +08:00
|
|
|
fi = rpmfiInit(fi, 0);
|
|
|
|
while ((i = rpmfiNext(fi)) >= 0) {
|
2002-07-28 08:41:15 +08:00
|
|
|
const char * fdn, * fbn;
|
2008-02-05 18:31:32 +08:00
|
|
|
rpm_mode_t fFMode;
|
2001-04-03 21:41:56 +08:00
|
|
|
|
2008-12-03 17:39:48 +08:00
|
|
|
if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
|
2007-09-12 01:07:39 +08:00
|
|
|
continue;
|
2002-07-28 08:41:15 +08:00
|
|
|
|
|
|
|
fFMode = rpmfiFMode(fi);
|
|
|
|
|
2007-09-26 14:57:26 +08:00
|
|
|
if (rpmfiWhatis(fFMode) != XDIR)
|
2007-09-12 01:07:39 +08:00
|
|
|
continue;
|
2002-07-28 08:41:15 +08:00
|
|
|
fdn = rpmfiDN(fi);
|
|
|
|
if (strlen(fdn) != dnlen)
|
2007-09-12 01:07:39 +08:00
|
|
|
continue;
|
2009-08-31 18:03:53 +08:00
|
|
|
if (!rstreqn(fdn, dn, dnlen))
|
2007-09-12 01:07:39 +08:00
|
|
|
continue;
|
2002-07-28 08:41:15 +08:00
|
|
|
fbn = rpmfiBN(fi);
|
|
|
|
if (strlen(fbn) != bnlen)
|
2007-09-12 01:07:39 +08:00
|
|
|
continue;
|
2009-08-31 18:03:53 +08:00
|
|
|
if (!rstreqn(fbn, bn, bnlen))
|
2007-09-12 01:07:39 +08:00
|
|
|
continue;
|
2008-03-07 15:47:51 +08:00
|
|
|
rpmlog(RPMLOG_DEBUG, "excluding directory %s\n", dn);
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, i, FA_SKIPNSTATE);
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-04-03 21:41:56 +08:00
|
|
|
}
|
2001-01-24 00:07:28 +08:00
|
|
|
}
|
2001-04-03 21:41:56 +08:00
|
|
|
|
2008-04-25 19:34:36 +08:00
|
|
|
free(drc);
|
|
|
|
free(dff);
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
1999-01-01 03:16:31 +08:00
|
|
|
|
2008-11-07 17:58:25 +08:00
|
|
|
#undef HASHTYPE
|
|
|
|
#undef HTKEYTYPE
|
|
|
|
#undef HTDATATYPE
|
|
|
|
|
|
|
|
#define HASHTYPE rpmStringSet
|
|
|
|
#define HTKEYTYPE const char *
|
|
|
|
#include "lib/rpmhash.H"
|
|
|
|
#include "lib/rpmhash.C"
|
|
|
|
|
|
|
|
/* Get a rpmdbMatchIterator containing all files in
|
|
|
|
* the rpmdb that share the basename with one from
|
|
|
|
* the transaction.
|
|
|
|
* @param ts transaction set
|
|
|
|
* @return rpmdbMatchIterator sorted
|
|
|
|
by (package, fileNum)
|
|
|
|
*/
|
|
|
|
static
|
2009-02-24 17:50:23 +08:00
|
|
|
rpmdbMatchIterator rpmFindBaseNamesInDB(rpmts ts, uint64_t fileCount)
|
2008-11-07 17:58:25 +08:00
|
|
|
{
|
2010-03-12 16:20:25 +08:00
|
|
|
tsMembers tsmem = rpmtsMembers(ts);
|
2008-11-07 17:58:25 +08:00
|
|
|
rpmtsi pi; rpmte p;
|
|
|
|
rpmfi fi;
|
|
|
|
rpmdbMatchIterator mi;
|
2009-12-17 23:28:37 +08:00
|
|
|
int oc = 0;
|
2008-11-07 17:58:25 +08:00
|
|
|
const char * baseName;
|
|
|
|
|
2009-02-24 17:50:23 +08:00
|
|
|
rpmStringSet baseNames = rpmStringSetCreate(fileCount,
|
2011-03-10 15:00:07 +08:00
|
|
|
rstrhash, strcmp, NULL);
|
2008-11-07 17:58:25 +08:00
|
|
|
|
2010-10-26 14:54:55 +08:00
|
|
|
mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_BASENAMES);
|
2008-11-07 17:58:25 +08:00
|
|
|
|
|
|
|
pi = rpmtsiInit(ts);
|
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
|
|
|
(void) rpmdbCheckSignals();
|
|
|
|
|
2010-03-12 16:20:25 +08:00
|
|
|
rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_PROGRESS, oc++, tsmem->orderCount);
|
2008-11-07 17:58:25 +08:00
|
|
|
|
|
|
|
/* Gather all installed headers with matching basename's. */
|
2009-12-17 23:28:37 +08:00
|
|
|
fi = rpmfiInit(rpmteFI(p), 0);
|
2009-09-07 17:23:21 +08:00
|
|
|
while (rpmfiNext(fi) >= 0) {
|
2008-11-07 17:58:25 +08:00
|
|
|
size_t keylen;
|
|
|
|
baseName = rpmfiBN(fi);
|
|
|
|
if (rpmStringSetHasEntry(baseNames, baseName))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
keylen = strlen(baseName);
|
|
|
|
if (keylen == 0)
|
|
|
|
keylen++; /* XXX "/" fixup. */
|
2011-04-19 15:02:23 +08:00
|
|
|
rpmdbExtendIterator(mi, baseName, keylen);
|
2008-11-07 17:58:25 +08:00
|
|
|
rpmStringSetAddEntry(baseNames, baseName);
|
|
|
|
}
|
|
|
|
}
|
2011-05-29 03:29:58 +08:00
|
|
|
rpmtsiFree(pi);
|
2008-11-07 17:58:25 +08:00
|
|
|
rpmStringSetFree(baseNames);
|
|
|
|
|
|
|
|
rpmdbSortIterator(mi);
|
|
|
|
/* iterator is now sorted by (recnum, filenum) */
|
|
|
|
return mi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check files in the transactions against the rpmdb
|
|
|
|
* Lookup all files with the same basename in the rpmdb
|
|
|
|
* and then check for matching finger prints
|
|
|
|
* @param ts transaction set
|
|
|
|
* @param fpc global finger print cache
|
|
|
|
*/
|
|
|
|
static
|
2009-02-24 17:50:23 +08:00
|
|
|
void checkInstalledFiles(rpmts ts, uint64_t fileCount, rpmFpHash ht, fingerPrintCache fpc)
|
2008-11-07 17:58:25 +08:00
|
|
|
{
|
2010-03-12 16:20:25 +08:00
|
|
|
tsMembers tsmem = rpmtsMembers(ts);
|
2008-11-07 17:58:25 +08:00
|
|
|
rpmte p;
|
2008-11-26 23:29:55 +08:00
|
|
|
rpmfi fi;
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfs fs;
|
2008-11-07 17:58:25 +08:00
|
|
|
rpmfi otherFi=NULL;
|
|
|
|
int j;
|
|
|
|
unsigned int fileNum;
|
|
|
|
const char * oldDir;
|
|
|
|
|
|
|
|
rpmdbMatchIterator mi;
|
|
|
|
Header h, newheader;
|
|
|
|
|
|
|
|
int beingRemoved;
|
|
|
|
|
|
|
|
rpmlog(RPMLOG_DEBUG, "computing file dispositions\n");
|
|
|
|
|
2009-02-24 17:50:23 +08:00
|
|
|
mi = rpmFindBaseNamesInDB(ts, fileCount);
|
2008-11-07 17:58:25 +08:00
|
|
|
|
|
|
|
/* For all installed headers with matching basename's ... */
|
|
|
|
if (mi == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (rpmdbGetIteratorCount(mi) == 0) {
|
|
|
|
mi = rpmdbFreeIterator(mi);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Loop over all packages from the rpmdb */
|
|
|
|
h = newheader = rpmdbNextIterator(mi);
|
|
|
|
while (h != NULL) {
|
|
|
|
headerGetFlags hgflags = HEADERGET_MINMEM;
|
|
|
|
struct rpmtd_s bnames, dnames, dindexes, ostates;
|
|
|
|
fingerPrint fp;
|
|
|
|
unsigned int installedPkg;
|
|
|
|
|
|
|
|
/* Is this package being removed? */
|
|
|
|
installedPkg = rpmdbGetIteratorOffset(mi);
|
2010-05-05 18:49:16 +08:00
|
|
|
beingRemoved = intHashHasEntry(tsmem->removedPackages, installedPkg);
|
2008-11-07 17:58:25 +08:00
|
|
|
|
|
|
|
h = headerLink(h);
|
|
|
|
headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags);
|
|
|
|
headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags);
|
|
|
|
headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags);
|
|
|
|
headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags);
|
|
|
|
|
|
|
|
oldDir = NULL;
|
2008-12-03 17:39:48 +08:00
|
|
|
/* loop over all interesting files in that package */
|
2008-11-07 17:58:25 +08:00
|
|
|
do {
|
|
|
|
int gotRecs;
|
|
|
|
struct rpmffi_s * recs;
|
|
|
|
int numRecs;
|
2008-11-25 21:33:11 +08:00
|
|
|
const char * dirName;
|
|
|
|
const char * baseName;
|
|
|
|
|
2008-11-07 17:58:25 +08:00
|
|
|
fileNum = rpmdbGetIteratorFileNum(mi);
|
2008-11-25 21:33:11 +08:00
|
|
|
rpmtdSetIndex(&bnames, fileNum);
|
|
|
|
rpmtdSetIndex(&dindexes, fileNum);
|
|
|
|
rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes));
|
|
|
|
rpmtdSetIndex(&ostates, fileNum);
|
|
|
|
|
|
|
|
dirName = rpmtdGetString(&dnames);
|
|
|
|
baseName = rpmtdGetString(&bnames);
|
|
|
|
|
2008-11-07 17:58:25 +08:00
|
|
|
/* lookup finger print for this file */
|
2008-11-25 21:33:11 +08:00
|
|
|
if ( dirName == oldDir) {
|
2008-11-07 17:58:25 +08:00
|
|
|
/* directory is the same as last round */
|
2008-11-25 21:33:11 +08:00
|
|
|
fp.baseName = baseName;
|
2008-11-07 17:58:25 +08:00
|
|
|
} else {
|
2008-11-25 21:33:11 +08:00
|
|
|
fp = fpLookup(fpc, dirName, baseName, 1);
|
|
|
|
oldDir = dirName;
|
2008-11-07 17:58:25 +08:00
|
|
|
}
|
|
|
|
/* search for files in the transaction with same finger print */
|
2009-02-24 17:23:25 +08:00
|
|
|
gotRecs = rpmFpHashGetEntry(ht, &fp, &recs, &numRecs, NULL);
|
2008-11-07 17:58:25 +08:00
|
|
|
|
|
|
|
for (j=0; (j<numRecs)&&gotRecs; j++) {
|
2008-11-26 23:29:55 +08:00
|
|
|
p = recs[j].p;
|
2008-11-27 16:02:00 +08:00
|
|
|
fi = rpmteFI(p);
|
2008-12-03 17:39:48 +08:00
|
|
|
fs = rpmteGetFileStates(p);
|
2008-11-07 17:58:25 +08:00
|
|
|
|
|
|
|
/* Determine the fate of each file. */
|
|
|
|
switch (rpmteType(p)) {
|
|
|
|
case TR_ADDED:
|
|
|
|
if (!otherFi) {
|
2008-12-09 00:46:36 +08:00
|
|
|
otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER);
|
2008-11-07 17:58:25 +08:00
|
|
|
}
|
2008-11-26 23:29:55 +08:00
|
|
|
rpmfiSetFX(fi, recs[j].fileno);
|
2008-11-07 17:58:25 +08:00
|
|
|
rpmfiSetFX(otherFi, fileNum);
|
2011-03-04 19:46:06 +08:00
|
|
|
handleInstInstalledFile(ts, p, fi, h, otherFi, beingRemoved);
|
2008-11-07 17:58:25 +08:00
|
|
|
break;
|
|
|
|
case TR_REMOVED:
|
|
|
|
if (!beingRemoved) {
|
2008-11-26 23:29:55 +08:00
|
|
|
rpmfiSetFX(fi, recs[j].fileno);
|
2008-11-25 21:33:11 +08:00
|
|
|
if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL)
|
2008-12-03 17:39:48 +08:00
|
|
|
rpmfsSetAction(fs, recs[j].fileno, FA_SKIP);
|
2008-11-07 17:58:25 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
newheader = rpmdbNextIterator(mi);
|
|
|
|
|
|
|
|
} while (newheader==h);
|
|
|
|
|
|
|
|
otherFi = rpmfiFree(otherFi);
|
|
|
|
rpmtdFreeData(&ostates);
|
|
|
|
rpmtdFreeData(&bnames);
|
|
|
|
rpmtdFreeData(&dnames);
|
|
|
|
rpmtdFreeData(&dindexes);
|
|
|
|
headerFree(h);
|
|
|
|
h = newheader;
|
|
|
|
}
|
|
|
|
|
2011-05-29 03:29:58 +08:00
|
|
|
rpmdbFreeIterator(mi);
|
2008-11-07 17:58:25 +08:00
|
|
|
}
|
|
|
|
|
2010-02-26 02:42:55 +08:00
|
|
|
#define badArch(_a) (rpmMachineScore(RPM_MACHTABLE_INSTARCH, (_a)) == 0)
|
|
|
|
#define badOs(_a) (rpmMachineScore(RPM_MACHTABLE_INSTOS, (_a)) == 0)
|
|
|
|
|
2009-02-24 16:13:43 +08:00
|
|
|
/*
|
|
|
|
* For packages being installed:
|
|
|
|
* - verify package arch/os.
|
|
|
|
* - verify package epoch:version-release is newer.
|
|
|
|
*/
|
|
|
|
static rpmps checkProblems(rpmts ts)
|
|
|
|
{
|
|
|
|
rpm_color_t tscolor = rpmtsColor(ts);
|
2010-02-26 02:42:55 +08:00
|
|
|
rpmprobFilterFlags probFilter = rpmtsFilterFlags(ts);
|
2009-02-24 16:13:43 +08:00
|
|
|
rpmtsi pi = rpmtsiInit(ts);
|
|
|
|
rpmte p;
|
|
|
|
|
|
|
|
/* The ordering doesn't matter here */
|
|
|
|
/* XXX Only added packages need be checked. */
|
|
|
|
rpmlog(RPMLOG_DEBUG, "sanity checking %d elements\n", rpmtsNElements(ts));
|
|
|
|
while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
|
|
|
|
|
2010-02-26 02:42:55 +08:00
|
|
|
if (!(probFilter & RPMPROB_FILTER_IGNOREARCH) && badArch(rpmteA(p)))
|
2010-03-26 16:27:39 +08:00
|
|
|
rpmteAddProblem(p, RPMPROB_BADARCH, rpmteA(p), NULL, 0);
|
2009-02-24 16:13:43 +08:00
|
|
|
|
2010-02-26 02:42:55 +08:00
|
|
|
if (!(probFilter & RPMPROB_FILTER_IGNOREOS) && badOs(rpmteO(p)))
|
2010-03-26 16:27:39 +08:00
|
|
|
rpmteAddProblem(p, RPMPROB_BADOS, rpmteO(p), NULL, 0);
|
2009-02-24 16:13:43 +08:00
|
|
|
|
2010-02-26 02:42:55 +08:00
|
|
|
if (!(probFilter & RPMPROB_FILTER_OLDPACKAGE)) {
|
2009-02-24 16:13:43 +08:00
|
|
|
Header h;
|
2011-05-30 16:45:41 +08:00
|
|
|
rpmdbMatchIterator mi;
|
2010-10-22 16:49:52 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMDBI_NAME, rpmteN(p), 0);
|
2009-02-24 16:13:43 +08:00
|
|
|
while ((h = rpmdbNextIterator(mi)) != NULL)
|
2010-03-13 01:41:10 +08:00
|
|
|
ensureOlder(p, h);
|
2011-05-30 16:45:41 +08:00
|
|
|
rpmdbFreeIterator(mi);
|
2009-02-24 16:13:43 +08:00
|
|
|
}
|
|
|
|
|
2010-02-26 02:42:55 +08:00
|
|
|
if (!(probFilter & RPMPROB_FILTER_REPLACEPKG)) {
|
2010-03-26 21:22:13 +08:00
|
|
|
Header h;
|
2011-05-30 16:45:41 +08:00
|
|
|
rpmdbMatchIterator mi;
|
2010-10-22 16:49:52 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMDBI_NAME, rpmteN(p), 0);
|
2009-02-24 16:13:43 +08:00
|
|
|
rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP, rpmteE(p));
|
|
|
|
rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP, rpmteV(p));
|
|
|
|
rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP, rpmteR(p));
|
|
|
|
if (tscolor) {
|
|
|
|
rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP, rpmteA(p));
|
|
|
|
rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP, rpmteO(p));
|
|
|
|
}
|
|
|
|
|
2010-03-26 21:22:13 +08:00
|
|
|
if ((h = rpmdbNextIterator(mi)) != NULL) {
|
|
|
|
rpmteAddProblem(p, RPMPROB_PKG_INSTALLED, NULL, NULL,
|
|
|
|
headerGetInstance(h));
|
2009-02-24 16:13:43 +08:00
|
|
|
}
|
2011-05-30 16:45:41 +08:00
|
|
|
rpmdbFreeIterator(mi);
|
2009-02-24 16:13:43 +08:00
|
|
|
}
|
|
|
|
}
|
2011-05-29 03:29:58 +08:00
|
|
|
rpmtsiFree(pi);
|
2010-03-13 01:41:10 +08:00
|
|
|
return rpmtsProblems(ts);
|
2009-02-24 16:13:43 +08:00
|
|
|
}
|
|
|
|
|
2008-03-17 22:03:51 +08:00
|
|
|
/*
|
|
|
|
* Run pre/post transaction scripts for transaction set
|
|
|
|
* param ts Transaction set
|
2010-03-29 23:36:21 +08:00
|
|
|
* param goal PKG_PRETRANS/PKG_POSTTRANS
|
|
|
|
* return 0 on success
|
2008-03-17 22:03:51 +08:00
|
|
|
*/
|
2010-03-29 23:36:21 +08:00
|
|
|
static int runTransScripts(rpmts ts, pkgGoal goal)
|
2008-03-17 22:03:51 +08:00
|
|
|
{
|
2011-11-22 17:24:22 +08:00
|
|
|
int rc = 0;
|
2008-03-17 22:03:51 +08:00
|
|
|
rpmte p;
|
2010-03-29 23:36:21 +08:00
|
|
|
rpmtsi pi = rpmtsiInit(ts);
|
2008-03-17 22:03:51 +08:00
|
|
|
while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
|
2011-11-22 17:24:22 +08:00
|
|
|
rc += rpmteProcess(p, goal);
|
2008-03-17 22:03:51 +08:00
|
|
|
}
|
2011-05-29 03:29:58 +08:00
|
|
|
rpmtsiFree(pi);
|
2011-11-22 17:24:22 +08:00
|
|
|
return rc;
|
2008-03-17 22:03:51 +08:00
|
|
|
}
|
|
|
|
|
2010-08-31 04:32:27 +08:00
|
|
|
static int rpmtsSetupCollections(rpmts ts)
|
2010-06-22 05:04:37 +08:00
|
|
|
{
|
|
|
|
/* seenCollectionsPost and TEs are basically a key-value pair. each item in
|
|
|
|
* seenCollectionsPost is a collection that has been seen from any package,
|
|
|
|
* and the associated index in the TEs is the last transaction element
|
|
|
|
* where that collection was seen. */
|
|
|
|
ARGV_t seenCollectionsPost = NULL;
|
|
|
|
rpmte *TEs = NULL;
|
|
|
|
int numSeenPost = 0;
|
|
|
|
|
|
|
|
/* seenCollectionsPre is a list of collections that have been seen from
|
|
|
|
* only removed packages */
|
|
|
|
ARGV_t seenCollectionsPre = NULL;
|
|
|
|
int numSeenPre = 0;
|
|
|
|
|
|
|
|
ARGV_const_t collname;
|
|
|
|
int installing = 1;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
rpmte p;
|
|
|
|
rpmtsi pi = rpmtsiInit(ts);
|
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
|
|
|
/* detect when we switch from installing to removing packages, and
|
|
|
|
* update the lastInCollectionAdd lists */
|
|
|
|
if (installing && rpmteType(p) == TR_REMOVED) {
|
|
|
|
installing = 0;
|
|
|
|
for (i = 0; i < numSeenPost; i++) {
|
|
|
|
rpmteAddToLastInCollectionAdd(TEs[i], seenCollectionsPost[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-31 04:32:27 +08:00
|
|
|
rpmteSetupCollectionPlugins(p);
|
|
|
|
|
2010-06-22 05:04:37 +08:00
|
|
|
for (collname = rpmteCollections(p); collname && *collname; collname++) {
|
|
|
|
/* figure out if we've seen this collection in post before */
|
|
|
|
for (i = 0; i < numSeenPost && strcmp(*collname, seenCollectionsPost[i]); i++) {
|
|
|
|
}
|
|
|
|
if (i < numSeenPost) {
|
|
|
|
/* we've seen the collection, update the index */
|
|
|
|
TEs[i] = p;
|
|
|
|
} else {
|
|
|
|
/* haven't seen the collection yet, add it */
|
|
|
|
argvAdd(&seenCollectionsPost, *collname);
|
|
|
|
TEs = xrealloc(TEs, sizeof(*TEs) * (numSeenPost + 1));
|
|
|
|
TEs[numSeenPost] = p;
|
|
|
|
numSeenPost++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* figure out if we've seen this collection in pre remove before */
|
|
|
|
if (installing == 0) {
|
|
|
|
for (i = 0; i < numSeenPre && strcmp(*collname, seenCollectionsPre[i]); i++) {
|
|
|
|
}
|
|
|
|
if (i >= numSeenPre) {
|
|
|
|
/* haven't seen this collection, add it */
|
|
|
|
rpmteAddToFirstInCollectionRemove(p, *collname);
|
|
|
|
argvAdd(&seenCollectionsPre, *collname);
|
|
|
|
numSeenPre++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-05-31 17:43:15 +08:00
|
|
|
rpmtsiFree(pi);
|
2010-06-22 05:04:37 +08:00
|
|
|
|
|
|
|
/* we've looked at all the rpmte's, update the lastInCollectionAny lists */
|
|
|
|
for (i = 0; i < numSeenPost; i++) {
|
|
|
|
rpmteAddToLastInCollectionAny(TEs[i], seenCollectionsPost[i]);
|
|
|
|
if (installing == 1) {
|
|
|
|
/* lastInCollectionAdd is only updated above if packages were
|
|
|
|
* removed. if nothing is removed in the transaction, we need to
|
|
|
|
* update that list here */
|
|
|
|
rpmteAddToLastInCollectionAdd(TEs[i], seenCollectionsPost[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
argvFree(seenCollectionsPost);
|
|
|
|
argvFree(seenCollectionsPre);
|
|
|
|
_free(TEs);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-02-24 17:15:53 +08:00
|
|
|
/* Add fingerprint for each file not skipped. */
|
2009-02-24 17:50:23 +08:00
|
|
|
static void addFingerprints(rpmts ts, uint64_t fileCount, rpmFpHash ht, fingerPrintCache fpc)
|
2009-02-24 16:40:43 +08:00
|
|
|
{
|
|
|
|
rpmtsi pi;
|
|
|
|
rpmte p;
|
|
|
|
rpmfi fi;
|
2009-02-24 17:15:53 +08:00
|
|
|
int i;
|
|
|
|
|
2009-02-24 17:50:23 +08:00
|
|
|
rpmFpHash symlinks = rpmFpHashCreate(fileCount/16+16, fpHashFunction, fpEqual, NULL, NULL);
|
2009-02-24 17:15:53 +08:00
|
|
|
|
|
|
|
pi = rpmtsiInit(ts);
|
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
|
|
|
(void) rpmdbCheckSignals();
|
|
|
|
|
|
|
|
if ((fi = rpmteFI(p)) == NULL)
|
|
|
|
continue; /* XXX can't happen */
|
|
|
|
|
|
|
|
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
|
|
|
|
rpmfiFpLookup(fi, fpc);
|
|
|
|
/* collect symbolic links */
|
|
|
|
fi = rpmfiInit(fi, 0);
|
|
|
|
while ((i = rpmfiNext(fi)) >= 0) {
|
|
|
|
struct rpmffi_s ffi;
|
|
|
|
char const *linktarget;
|
|
|
|
linktarget = rpmfiFLink(fi);
|
|
|
|
if (!(linktarget && *linktarget != '\0'))
|
|
|
|
continue;
|
|
|
|
if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i)))
|
|
|
|
continue;
|
|
|
|
ffi.p = p;
|
|
|
|
ffi.fileno = i;
|
|
|
|
rpmFpHashAddEntry(symlinks, rpmfiFpsIndex(fi, i), ffi);
|
|
|
|
}
|
2009-02-24 18:22:21 +08:00
|
|
|
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), rpmfiFC(fi));
|
2009-02-24 17:15:53 +08:00
|
|
|
|
|
|
|
}
|
2011-05-31 17:43:15 +08:00
|
|
|
rpmtsiFree(pi);
|
2009-02-24 17:15:53 +08:00
|
|
|
|
|
|
|
/* ===============================================
|
|
|
|
* Check fingerprints if they contain symlinks
|
2009-02-24 17:23:25 +08:00
|
|
|
* and add them to the hash table
|
2009-02-24 17:15:53 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
pi = rpmtsiInit(ts);
|
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
|
|
|
(void) rpmdbCheckSignals();
|
|
|
|
|
2010-02-26 02:52:35 +08:00
|
|
|
fi = rpmfiInit(rpmteFI(p), 0);
|
2009-02-24 17:15:53 +08:00
|
|
|
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
|
|
|
|
while ((i = rpmfiNext(fi)) >= 0) {
|
|
|
|
if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i)))
|
|
|
|
continue;
|
2009-02-24 17:23:25 +08:00
|
|
|
fpLookupSubdir(symlinks, ht, fpc, p, i);
|
2009-02-24 17:15:53 +08:00
|
|
|
}
|
|
|
|
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
|
|
|
|
}
|
2011-05-31 17:43:15 +08:00
|
|
|
rpmtsiFree(pi);
|
2009-02-24 17:15:53 +08:00
|
|
|
|
|
|
|
rpmFpHashFree(symlinks);
|
|
|
|
}
|
|
|
|
|
2009-02-24 19:41:18 +08:00
|
|
|
static int rpmtsSetup(rpmts ts, rpmprobFilterFlags ignoreSet)
|
|
|
|
{
|
|
|
|
rpm_tid_t tid = (rpm_tid_t) time(NULL);
|
|
|
|
int dbmode = (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) ? O_RDONLY : (O_RDWR|O_CREAT);
|
|
|
|
|
|
|
|
if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS)
|
|
|
|
(void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
|
|
|
|
if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS)
|
|
|
|
(void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));
|
|
|
|
|
2011-05-25 19:52:39 +08:00
|
|
|
if (rpmtsFlags(ts) & (RPMTRANS_FLAG_JUSTDB | RPMTRANS_FLAG_TEST))
|
|
|
|
(void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers | RPMTRANS_FLAG_NOCOLLECTIONS));
|
2009-02-24 19:41:18 +08:00
|
|
|
|
2010-06-11 13:19:08 +08:00
|
|
|
/* if SELinux isn't enabled, init fails or test run, don't bother... */
|
2010-08-13 15:58:51 +08:00
|
|
|
if (!is_selinux_enabled() || (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
|
2009-02-24 19:41:18 +08:00
|
|
|
rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
|
Use selabel interfaces instead of matchpathcon
This replaces the old matchpathcon interfaces with the new selabel
interfaces for relabeling files, storing an selabel handle in the
transaction set.
With this change, also comes an added distinction between --nocontexts
being specified and a failure to read the load file contexts.
Previously, there was no distinction, and both cases used the
RPMTRANS_FLAG_NOCONTEXTS flag.
However, with the new policy plugin, it is necessary to make such a
distinction. This is because matchpathcon_init (now selabel interfaces)
can fail at the beginning of the transaction, but succeed later after
new policy is installed. Because of this, we may need to enable/disable
RPMTRANS_FLAG_NOCONTEXTS multiple times. However, because this flag
could also mean --nocontexts, we cannot do that. By storing the selabel
handle in the rpmts, we can easily keep track if the handle has been
successfully created, rather than overloading RPMTRANS_FLAG_NOCONTEXTS
with two meanings.
2010-08-31 04:32:30 +08:00
|
|
|
rpmtsSELabelInit(ts, selinux_file_context_path());
|
2009-02-24 19:41:18 +08:00
|
|
|
}
|
|
|
|
|
2011-01-28 19:15:09 +08:00
|
|
|
/*
|
|
|
|
* Make sure the database is open RDWR for package install/erase.
|
|
|
|
* Note that we initialize chroot state here even if it's just "/" as
|
|
|
|
* this ensures we can successfully perform open(".") which is
|
|
|
|
* required to reliably restore cwd after Lua scripts.
|
|
|
|
*/
|
2010-05-31 19:07:46 +08:00
|
|
|
if (rpmtsOpenDB(ts, dbmode) || rpmChrootSet(rpmtsRootDir(ts)))
|
|
|
|
return -1;
|
2009-02-24 19:41:18 +08:00
|
|
|
|
|
|
|
ts->ignoreSet = ignoreSet;
|
|
|
|
(void) rpmtsSetTid(ts, tid);
|
|
|
|
|
|
|
|
/* Get available space on mounted file systems. */
|
|
|
|
(void) rpmtsInitDSI(ts);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rpmtsFinish(rpmts ts)
|
|
|
|
{
|
|
|
|
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
|
Use selabel interfaces instead of matchpathcon
This replaces the old matchpathcon interfaces with the new selabel
interfaces for relabeling files, storing an selabel handle in the
transaction set.
With this change, also comes an added distinction between --nocontexts
being specified and a failure to read the load file contexts.
Previously, there was no distinction, and both cases used the
RPMTRANS_FLAG_NOCONTEXTS flag.
However, with the new policy plugin, it is necessary to make such a
distinction. This is because matchpathcon_init (now selabel interfaces)
can fail at the beginning of the transaction, but succeed later after
new policy is installed. Because of this, we may need to enable/disable
RPMTRANS_FLAG_NOCONTEXTS multiple times. However, because this flag
could also mean --nocontexts, we cannot do that. By storing the selabel
handle in the rpmts, we can easily keep track if the handle has been
successfully created, rather than overloading RPMTRANS_FLAG_NOCONTEXTS
with two meanings.
2010-08-31 04:32:30 +08:00
|
|
|
rpmtsSELabelFini(ts);
|
2009-02-24 19:41:18 +08:00
|
|
|
}
|
2010-05-31 19:07:46 +08:00
|
|
|
return rpmChrootSet(NULL);
|
2009-02-24 19:41:18 +08:00
|
|
|
}
|
|
|
|
|
2009-02-24 18:13:26 +08:00
|
|
|
static int rpmtsPrepare(rpmts ts)
|
2009-02-24 17:15:53 +08:00
|
|
|
{
|
2010-03-12 16:20:25 +08:00
|
|
|
tsMembers tsmem = rpmtsMembers(ts);
|
2009-02-24 17:15:53 +08:00
|
|
|
rpmtsi pi;
|
|
|
|
rpmte p;
|
|
|
|
rpmfi fi;
|
2010-05-31 23:00:33 +08:00
|
|
|
int rc = 0;
|
2009-02-24 17:50:23 +08:00
|
|
|
uint64_t fileCount = countFiles(ts);
|
2009-02-24 17:15:53 +08:00
|
|
|
|
2009-02-24 17:50:23 +08:00
|
|
|
fingerPrintCache fpc = fpCacheCreate(fileCount/2 + 10001);
|
|
|
|
rpmFpHash ht = rpmFpHashCreate(fileCount/2+1, fpHashFunction, fpEqual,
|
2009-02-24 17:15:53 +08:00
|
|
|
NULL, NULL);
|
2010-02-02 18:25:59 +08:00
|
|
|
rpmDiskSpaceInfo dsi;
|
2009-02-24 16:40:43 +08:00
|
|
|
|
2009-02-24 17:50:23 +08:00
|
|
|
rpmlog(RPMLOG_DEBUG, "computing %" PRIu64 " file fingerprints\n", fileCount);
|
|
|
|
|
|
|
|
/* Skip netshared paths, not our i18n files, and excluded docs */
|
|
|
|
pi = rpmtsiInit(ts);
|
2009-09-14 22:19:33 +08:00
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
2010-02-26 02:52:35 +08:00
|
|
|
if (rpmfiFC(rpmteFI(p)) == 0)
|
2009-09-14 22:19:33 +08:00
|
|
|
continue;
|
|
|
|
if (rpmteType(p) == TR_ADDED) {
|
|
|
|
skipInstallFiles(ts, p);
|
|
|
|
} else {
|
|
|
|
skipEraseFiles(ts, p);
|
|
|
|
}
|
2009-02-24 17:50:23 +08:00
|
|
|
}
|
2011-05-31 17:43:15 +08:00
|
|
|
rpmtsiFree(pi);
|
2009-02-24 17:50:23 +08:00
|
|
|
|
2010-05-31 19:07:46 +08:00
|
|
|
/* Open rpmdb & enter chroot for fingerprinting if necessary */
|
|
|
|
if (rpmdbOpenAll(ts->rdb) || rpmChrootIn()) {
|
|
|
|
rc = -1;
|
|
|
|
goto exit;
|
2009-02-24 18:13:26 +08:00
|
|
|
}
|
|
|
|
|
2010-03-12 16:20:25 +08:00
|
|
|
rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, tsmem->orderCount);
|
2009-02-24 17:50:23 +08:00
|
|
|
addFingerprints(ts, fileCount, ht, fpc);
|
2009-02-24 16:40:43 +08:00
|
|
|
/* check against files in the rpmdb */
|
2009-02-24 17:50:23 +08:00
|
|
|
checkInstalledFiles(ts, fileCount, ht, fpc);
|
2009-02-24 16:40:43 +08:00
|
|
|
|
2010-02-02 18:25:59 +08:00
|
|
|
dsi = rpmtsDbDSI(ts);
|
|
|
|
|
2009-02-24 16:40:43 +08:00
|
|
|
pi = rpmtsiInit(ts);
|
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
|
|
|
if ((fi = rpmteFI(p)) == NULL)
|
|
|
|
continue; /* XXX can't happen */
|
|
|
|
|
|
|
|
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
|
|
|
|
/* check files in ts against each other and update disk space
|
|
|
|
needs on each partition for this package. */
|
2009-02-24 17:23:25 +08:00
|
|
|
handleOverlappedFiles(ts, ht, p, fi);
|
2009-02-24 16:40:43 +08:00
|
|
|
|
2010-02-02 18:25:59 +08:00
|
|
|
rpmtsUpdateDSIrpmDBSize(p, dsi);
|
|
|
|
|
2009-02-24 16:40:43 +08:00
|
|
|
/* Check added package has sufficient space on each partition used. */
|
|
|
|
if (rpmteType(p) == TR_ADDED) {
|
|
|
|
rpmtsCheckDSIProblems(ts, p);
|
|
|
|
}
|
|
|
|
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
|
|
|
|
}
|
2011-05-31 17:43:15 +08:00
|
|
|
rpmtsiFree(pi);
|
2010-03-12 16:20:25 +08:00
|
|
|
rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, tsmem->orderCount);
|
2009-02-24 17:15:53 +08:00
|
|
|
|
2009-02-24 18:13:26 +08:00
|
|
|
/* return from chroot if done earlier */
|
2010-05-31 19:07:46 +08:00
|
|
|
if (rpmChrootOut())
|
|
|
|
rc = -1;
|
2009-02-24 18:13:26 +08:00
|
|
|
|
2009-02-24 17:50:23 +08:00
|
|
|
/* File info sets, fp caches etc not needed beyond here, free 'em up. */
|
|
|
|
pi = rpmtsiInit(ts);
|
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
|
|
|
rpmteSetFI(p, NULL);
|
|
|
|
}
|
2011-05-31 17:43:15 +08:00
|
|
|
rpmtsiFree(pi);
|
2009-02-24 18:13:26 +08:00
|
|
|
|
|
|
|
exit:
|
2011-05-29 03:29:58 +08:00
|
|
|
rpmFpHashFree(ht);
|
|
|
|
fpCacheFree(fpc);
|
2010-02-03 18:45:21 +08:00
|
|
|
rpmtsFreeDSI(ts);
|
2009-02-24 18:13:26 +08:00
|
|
|
return rc;
|
2009-02-24 16:40:43 +08:00
|
|
|
}
|
|
|
|
|
2008-11-24 21:31:31 +08:00
|
|
|
/*
|
|
|
|
* Transaction main loop: install and remove packages
|
|
|
|
*/
|
|
|
|
static int rpmtsProcess(rpmts ts)
|
|
|
|
{
|
|
|
|
rpmtsi pi; rpmte p;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
pi = rpmtsiInit(ts);
|
|
|
|
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
2010-03-29 23:36:21 +08:00
|
|
|
int failed;
|
2008-11-24 21:31:31 +08:00
|
|
|
|
2008-11-24 21:33:23 +08:00
|
|
|
rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n",
|
|
|
|
rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
|
|
|
|
|
2010-05-07 19:31:25 +08:00
|
|
|
failed = rpmteProcess(p, rpmteType(p));
|
2008-11-25 17:46:20 +08:00
|
|
|
if (failed) {
|
2010-02-25 18:36:09 +08:00
|
|
|
rpmlog(RPMLOG_ERR, "%s: %s %s\n", rpmteNEVRA(p),
|
2010-03-29 23:36:21 +08:00
|
|
|
rpmteTypeString(p), failed > 1 ? _("skipped") : _("failed"));
|
2008-11-25 17:46:20 +08:00
|
|
|
rc++;
|
|
|
|
}
|
2008-11-24 21:31:31 +08:00
|
|
|
(void) rpmdbSync(rpmtsGetRdb(ts));
|
|
|
|
}
|
2011-05-29 03:29:58 +08:00
|
|
|
rpmtsiFree(pi);
|
2008-11-24 21:31:31 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2004-03-27 01:27:57 +08:00
|
|
|
int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
|
|
|
|
{
|
2009-02-24 19:55:27 +08:00
|
|
|
int rc = -1; /* assume failure */
|
2010-04-22 15:37:51 +08:00
|
|
|
rpmlock lock = NULL;
|
2010-03-13 01:41:10 +08:00
|
|
|
rpmps tsprobs = NULL;
|
2010-11-18 18:50:55 +08:00
|
|
|
/* Force default 022 umask during transaction for consistent results */
|
|
|
|
mode_t oldmask = umask(022);
|
2001-11-12 00:17:57 +08:00
|
|
|
|
2011-05-18 13:28:07 +08:00
|
|
|
/* Empty transaction, nothing to do */
|
2009-02-24 19:55:27 +08:00
|
|
|
if (rpmtsNElements(ts) <= 0) {
|
2011-05-18 13:28:07 +08:00
|
|
|
rc = 0;
|
2009-02-24 19:55:27 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2001-11-12 00:17:57 +08:00
|
|
|
|
2004-10-10 03:40:09 +08:00
|
|
|
/* If we are in test mode, then there's no need for transaction lock. */
|
2008-03-17 18:04:39 +08:00
|
|
|
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
|
2009-02-24 19:55:27 +08:00
|
|
|
if (!(lock = rpmtsAcquireLock(ts))) {
|
|
|
|
goto exit;
|
|
|
|
}
|
2004-04-08 07:50:35 +08:00
|
|
|
}
|
2004-03-27 01:27:57 +08:00
|
|
|
|
2009-02-24 19:41:18 +08:00
|
|
|
/* Setup flags and such, open the DB */
|
|
|
|
if (rpmtsSetup(ts, ignoreSet)) {
|
2009-02-24 19:55:27 +08:00
|
|
|
goto exit;
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
|
|
|
|
2010-08-31 04:32:27 +08:00
|
|
|
rpmtsSetupCollections(ts);
|
2010-06-22 05:04:37 +08:00
|
|
|
|
2009-02-24 16:13:43 +08:00
|
|
|
/* Check package set for problems */
|
2010-03-13 01:41:10 +08:00
|
|
|
tsprobs = checkProblems(ts);
|
1999-10-20 18:22:46 +08:00
|
|
|
|
2004-03-27 01:27:57 +08:00
|
|
|
/* Run pre-transaction scripts, but only if there are no known
|
2009-01-17 20:15:50 +08:00
|
|
|
* problems up to this point and not disabled otherwise. */
|
2010-05-26 18:25:39 +08:00
|
|
|
if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_NOPRE))
|
2010-04-14 19:14:52 +08:00
|
|
|
|| (rpmpsNumProblems(tsprobs)))) {
|
2008-03-07 15:47:51 +08:00
|
|
|
rpmlog(RPMLOG_DEBUG, "running pre-transaction scripts\n");
|
2011-11-22 17:24:22 +08:00
|
|
|
if (runTransScripts(ts, PKG_PRETRANS))
|
|
|
|
goto exit;
|
1999-07-14 22:36:10 +08:00
|
|
|
}
|
2010-03-13 01:41:10 +08:00
|
|
|
tsprobs = rpmpsFree(tsprobs);
|
1999-02-21 11:34:52 +08:00
|
|
|
|
2009-02-24 16:40:43 +08:00
|
|
|
/* Compute file disposition for each package in transaction set. */
|
2009-02-24 18:13:26 +08:00
|
|
|
if (rpmtsPrepare(ts)) {
|
2009-02-24 19:55:27 +08:00
|
|
|
goto exit;
|
2004-03-27 01:27:57 +08:00
|
|
|
}
|
2010-03-13 01:41:10 +08:00
|
|
|
/* Check again for problems (now including file conflicts, duh */
|
|
|
|
tsprobs = rpmtsProblems(ts);
|
2003-11-24 03:50:52 +08:00
|
|
|
|
2009-02-24 18:35:21 +08:00
|
|
|
/* If unfiltered problems exist, free memory and return. */
|
2010-04-14 19:14:52 +08:00
|
|
|
if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) || (rpmpsNumProblems(tsprobs))) {
|
2010-03-12 16:20:25 +08:00
|
|
|
tsMembers tsmem = rpmtsMembers(ts);
|
|
|
|
rc = tsmem->orderCount;
|
2009-02-24 19:55:27 +08:00
|
|
|
goto exit;
|
2004-03-27 01:27:57 +08:00
|
|
|
}
|
2004-03-06 02:22:25 +08:00
|
|
|
|
2010-03-13 01:41:10 +08:00
|
|
|
/* Free up memory taken by problem sets */
|
|
|
|
tsprobs = rpmpsFree(tsprobs);
|
|
|
|
rpmtsCleanProblems(ts);
|
|
|
|
|
2009-02-24 19:55:27 +08:00
|
|
|
/* Actually install and remove packages, get final exit code */
|
|
|
|
rc = rpmtsProcess(ts) ? -1 : 0;
|
2004-03-06 02:22:25 +08:00
|
|
|
|
2009-02-24 19:55:27 +08:00
|
|
|
/* Run post-transaction scripts unless disabled */
|
2010-05-26 18:25:39 +08:00
|
|
|
if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOST))) {
|
2008-03-07 15:47:51 +08:00
|
|
|
rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n");
|
2010-03-29 23:36:21 +08:00
|
|
|
runTransScripts(ts, PKG_POSTTRANS);
|
2004-03-27 01:27:57 +08:00
|
|
|
}
|
|
|
|
|
2010-11-17 22:27:10 +08:00
|
|
|
exit:
|
2009-02-24 19:41:18 +08:00
|
|
|
/* Finish up... */
|
2010-11-18 18:50:55 +08:00
|
|
|
(void) umask(oldmask);
|
2009-02-24 19:41:18 +08:00
|
|
|
(void) rpmtsFinish(ts);
|
2011-05-29 03:29:58 +08:00
|
|
|
rpmpsFree(tsprobs);
|
2010-04-22 16:01:27 +08:00
|
|
|
rpmlockFree(lock);
|
2009-02-24 19:55:27 +08:00
|
|
|
return rc;
|
2004-03-06 02:22:25 +08:00
|
|
|
}
|