示例#1
0
文件: psm.c 项目: fingunter/rpm
static rpmpsm rpmpsmNew(rpmts ts, rpmte te, pkgGoal goal)
{
    rpmpsm psm = xcalloc(1, sizeof(*psm));
    psm->ts = rpmtsLink(ts);
    psm->files = rpmteFiles(te);
    psm->te = te; /* XXX rpmte not refcounted yet */
    if (!rpmteIsSource(te)) {
	/*
	 * When we run scripts, we pass an argument which is the number of
	 * versions of this package that will be installed when we are
	 * finished.
	 */
	int npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(te));
	switch (goal) {
	case PKG_INSTALL:
	case PKG_PRETRANS:
	    psm->scriptArg = npkgs_installed + 1;
	    psm->countCorrection = 0;
	    break;
	case PKG_ERASE:
	    psm->scriptArg = npkgs_installed - 1;
	    psm->countCorrection = -1;
	    break;
	case PKG_VERIFY:
	case PKG_POSTTRANS:
	    psm->scriptArg = npkgs_installed;
	    psm->countCorrection = 0;
	    break;
	default:
	    break;
	}
    }

    if (goal == PKG_INSTALL) {
	Header h = rpmteHeader(te);
	psm->total = headerGetNumber(h, RPMTAG_LONGARCHIVESIZE);
	headerFree(h);
    } else if (goal == PKG_ERASE) {
	psm->total = rpmfilesFC(psm->files);
    }
    /* Fake up something for packages with no files */
    if (psm->total == 0)
	psm->total = 100;

    rpmlog(RPMLOG_DEBUG, "%s: %s has %d files\n", pkgGoalString(goal),
	    rpmteNEVRA(psm->te), rpmfilesFC(psm->files));

    return psm;
}
示例#2
0
文件: rpmal.c 项目: Distrotech/rpm
static void rpmalAddFiles(rpmal al, rpmalNum pkgNum, rpmfiles fi)
{
    struct availableIndexFileEntry_s fileEntry;
    int fc = rpmfilesFC(fi);
    rpm_color_t ficolor;
    int skipdoc = (al->tsflags & RPMTRANS_FLAG_NODOCS);
    int skipconf = (al->tsflags & RPMTRANS_FLAG_NOCONFIGS);

    fileEntry.pkgNum = pkgNum;

    for (int i = 0; i < fc; i++) {
	/* Ignore colored provides not in our rainbow. */
        ficolor = rpmfilesFColor(fi, i);
        if (al->tscolor && ficolor && !(al->tscolor & ficolor))
            continue;

	/* Ignore files that wont be installed */
	if (skipdoc && (rpmfilesFFlags(fi, i) & RPMFILE_DOC))
	    continue;
	if (skipconf && (rpmfilesFFlags(fi, i) & RPMFILE_CONFIG))
	    continue;

	fileEntry.dirName = rpmfilesDNId(fi, rpmfilesDI(fi, i));
	fileEntry.entryIx = i;

	rpmalFileHashAddEntry(al->fileHash, rpmfilesBNId(fi, i), fileEntry);
    }
}
示例#3
0
/* Calculate total number of files involved in transaction */
static uint64_t countFiles(rpmts ts)
{
    uint64_t fc = 0;
    rpmtsi pi = rpmtsiInit(ts);
    rpmte p;
    rpmfiles files;
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	files = rpmteFiles(p);
	fc += rpmfilesFC(files);
	rpmfilesFree(files);
    }
    rpmtsiFree(pi);
    return fc;
}
示例#4
0
文件: rpmal.c 项目: Distrotech/rpm
static void rpmalMakeFileIndex(rpmal al)
{
    availablePackage alp;
    int i, fileCnt = 0;

    for (i = 0; i < al->size; i++) {
	alp = al->list + i;
	if (alp->fi != NULL)
	    fileCnt += rpmfilesFC(alp->fi);
    }
    al->fileHash = rpmalFileHashCreate(fileCnt/4+128,
				       sidHash, sidCmp, NULL, NULL);
    for (i = 0; i < al->size; i++) {
	alp = al->list + i;
	rpmalAddFiles(al, i, alp->fi);
    }
}
示例#5
0
文件: psm.c 项目: fingunter/rpm
static rpmRC rpmpsmUnpack(rpmpsm psm)
{
    char *failedFile = NULL;
    int fsmrc = 0;
    int saved_errno = 0;
    rpmRC rc = RPMRC_OK;

    rpmpsmNotify(psm, RPMCALLBACK_INST_START, 0);
    /* make sure first progress call gets made */
    rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, 0);

    if (!(rpmtsFlags(psm->ts) & RPMTRANS_FLAG_JUSTDB)) {
	if (rpmfilesFC(psm->files) > 0) {
	    fsmrc = rpmPackageFilesInstall(psm->ts, psm->te, psm->files,
				   psm, &failedFile);
	    saved_errno = errno;
	}
    }

    /* XXX make sure progress reaches 100% */
    rpmpsmNotify(psm, RPMCALLBACK_INST_PROGRESS, psm->total);
    rpmpsmNotify(psm, RPMCALLBACK_INST_STOP, psm->total);

    if (fsmrc) {
	char *emsg;
	errno = saved_errno;
	emsg = rpmfileStrerror(fsmrc);
	rpmlog(RPMLOG_ERR,
		_("unpacking of archive failed%s%s: %s\n"),
		(failedFile != NULL ? _(" on file ") : ""),
		(failedFile != NULL ? failedFile : ""),
		emsg);
	free(emsg);
	rc = RPMRC_FAIL;

	/* XXX notify callback on error. */
	rpmtsNotify(psm->ts, psm->te, RPMCALLBACK_UNPACK_ERROR, 0, 0);
    }
    free(failedFile);
    return rc;
}
示例#6
0
文件: psm.c 项目: fingunter/rpm
static rpmRC rpmpsmRemove(rpmpsm psm)
{
    char *failedFile = NULL;
    int fsmrc = 0;

    rpmpsmNotify(psm, RPMCALLBACK_UNINST_START, 0);
    /* make sure first progress call gets made */
    rpmpsmNotify(psm, RPMCALLBACK_UNINST_PROGRESS, 0);

    /* XXX should't we log errors from here? */
    if (!(rpmtsFlags(psm->ts) & RPMTRANS_FLAG_JUSTDB)) {
	if (rpmfilesFC(psm->files) > 0) {
	    fsmrc = rpmPackageFilesRemove(psm->ts, psm->te, psm->files,
					  psm, &failedFile);
	}
    }
    /* XXX make sure progress reaches 100% */
    rpmpsmNotify(psm, RPMCALLBACK_UNINST_PROGRESS, psm->total);
    rpmpsmNotify(psm, RPMCALLBACK_UNINST_STOP, psm->total);

    free(failedFile);
    return (fsmrc == 0) ? RPMRC_OK : RPMRC_FAIL;
}
示例#7
0
/* XXX only ts->{probs,di} modified */
static void handleOverlappedFiles(rpmts ts, fingerPrintCache fpc, rpmte p, rpmfiles fi)
{
    rpm_loff_t fixupSize = 0;
    int i, j;
    rpmfs fs = rpmteGetFileStates(p);
    rpmfs otherFs;
    rpm_count_t fc = rpmfilesFC(fi);
    int reportConflicts = !(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
    fingerPrint * fpList = rpmfilesFps(fi);

    for (i = 0; i < fc; i++) {
	struct fingerPrint_s * fiFps;
	int otherPkgNum, otherFileNum;
	rpmfiles otherFi;
	rpmte otherTe;
	rpmfileAttrs FFlags;
	struct rpmffi_s * recs;
	int numRecs;

	if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
	    continue;

	FFlags = rpmfilesFFlags(fi, i);

	fixupSize = 0;

	/*
	 * 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.
	 */
	fiFps = fpCacheGetByFp(fpc, fpList, i, &recs, &numRecs);

	/*
	 * If this package is being added, look only at other packages
	 * being added -- removed packages dance to a different tune.
	 *
	 * 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 occurrence of an overlapped
	 * file in the transaction set.
	 *
	 */

	/*
	 * Locate this overlapped file in the set of added/removed packages,
	 * including the package owning it: a package can have self-conflicting
	 * files when directory symlinks are present. Don't compare a file
	 * with itself though...
	 */
	for (j = 0; j < numRecs && !(recs[j].p == p && recs[j].fileno == i); j++)
	    {};

	/* Find what the previous disposition of this file was. */
	otherFileNum = -1;			/* keep gcc quiet */
	otherFi = NULL;
	otherTe = NULL;
	otherFs = NULL;

	for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
	    otherTe = recs[otherPkgNum].p;
	    otherFileNum = recs[otherPkgNum].fileno;
	    otherFs = rpmteGetFileStates(otherTe);

	    /* Added packages need only look at other added packages. */
	    if (rpmteType(p) == TR_ADDED && rpmteType(otherTe) != TR_ADDED)
		continue;

	    /* XXX Happens iff fingerprint for incomplete package install. */
	    if (rpmfsGetAction(otherFs, otherFileNum) != FA_UNKNOWN) {
		otherFi = rpmteFiles(otherTe);
		break;
	    }
	}

	switch (rpmteType(p)) {
	case TR_ADDED:
	    if (otherPkgNum < 0) {
		/* XXX is this test still necessary? */
		rpmFileAction action;
		if (rpmfsGetAction(fs, i) != FA_UNKNOWN)
		    break;
		if (rpmfilesConfigConflict(fi, i)) {
		    /* Here is a non-overlapped pre-existing config file. */
		    action = (FFlags & RPMFILE_NOREPLACE) ?
			      FA_ALTNAME : FA_BACKUP;
		} else {
		    action = FA_CREATE;
		}
		rpmfsSetAction(fs, i, action);
		break;
	    }

assert(otherFi != NULL);
	    /* Mark added overlapped non-identical files as a conflict. */
	    if (rpmfilesCompare(otherFi, otherFileNum, fi, i)) {
		int rConflicts;

		/* If enabled, resolve colored conflicts to preferred type */
		rConflicts = handleColorConflict(ts, fs, fi, i,
						otherFs, otherFi, otherFileNum);

		if (rConflicts && reportConflicts) {
		    char *fn = rpmfilesFN(fi, i);
		    rpmteAddProblem(p, RPMPROB_NEW_FILE_CONFLICT,
				    rpmteNEVRA(otherTe), fn, 0);
		    free(fn);
		}
	    } else {
		/* Skip create on all but the first instance of a shared file */
		rpmFileAction oaction = rpmfsGetAction(otherFs, otherFileNum);
		if (oaction != FA_UNKNOWN && !XFA_SKIPPING(oaction)) {
		    rpmfileAttrs oflags;
		    /* ...but ghosts aren't really created so... */
		    oflags = rpmfilesFFlags(otherFi, otherFileNum);
		    if (!(oflags & RPMFILE_GHOST)) {
			rpmfsSetAction(fs, i, FA_SKIP);
		    }
		/* if the other file is color skipped then skip this file too */
		} else if (oaction == FA_SKIPCOLOR) {
		    rpmfsSetAction(fs, i, FA_SKIPCOLOR);
		}
	    }

	    /* Skipped files dont need fixup size or backups, %config or not */
	    if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
		break;

	    /* Try to get the disk accounting correct even if a conflict. */
	    fixupSize = rpmfilesFSize(otherFi, otherFileNum);

	    if (rpmfilesConfigConflict(fi, i)) {
		/* Here is an overlapped  pre-existing config file. */
		rpmFileAction action;
		action = (FFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SKIP;
		rpmfsSetAction(fs, i, action);
	    } else {
		/* If not decided yet, create it */
		if (rpmfsGetAction(fs, i) == FA_UNKNOWN)
		    rpmfsSetAction(fs, i, FA_CREATE);
	    }
	    break;

	case TR_REMOVED:
	    if (otherPkgNum >= 0) {
		assert(otherFi != NULL);
                /* Here is an overlapped added file we don't want to nuke. */
		if (rpmfsGetAction(otherFs, otherFileNum) != FA_ERASE) {
		    /* On updates, don't remove files. */
		    rpmfsSetAction(fs, i, FA_SKIP);
		    break;
		}
		/* Here is an overlapped removed file: skip in previous. */
		rpmfsSetAction(otherFs, otherFileNum, FA_SKIP);
	    }
	    if (XFA_SKIPPING(rpmfsGetAction(fs, i)))
		break;
	    if (rpmfilesFState(fi, i) != RPMFILE_STATE_NORMAL)
		break;
		
	    /* Pre-existing modified config files need to be saved. */
	    if (rpmfilesConfigConflict(fi, i)) {
		rpmfsSetAction(fs, i, FA_SAVE);
		break;
	    }
	
	    /* Otherwise, we can just erase. */
	    rpmfsSetAction(fs, i, FA_ERASE);
	    break;
	}
	rpmfilesFree(otherFi);

	/* Update disk space info for a file. */
	rpmtsUpdateDSI(ts, fpEntryDev(fpc, fiFps), fpEntryDir(fpc, fiFps),
		       rpmfilesFSize(fi, i), rpmfilesFReplacedSize(fi, i),
		       fixupSize, rpmfsGetAction(fs, i));

    }
}
示例#8
0
static int rpmtsPrepare(rpmts ts)
{
    tsMembers tsmem = rpmtsMembers(ts);
    rpmtsi pi;
    rpmte p;
    int rc = 0;
    uint64_t fileCount = countFiles(ts);
    const char *dbhome = NULL;
    struct stat dbstat;

    fingerPrintCache fpc = fpCacheCreate(fileCount/2 + 10001, rpmtsPool(ts));

    rpmlog(RPMLOG_DEBUG, "computing %" PRIu64 " file fingerprints\n", fileCount);

    /* Reset actions, set skip for netshared paths and excluded files */
    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	rpmfiles files = rpmteFiles(p);
	if (rpmfilesFC(files) > 0) {
	    rpmfs fs = rpmteGetFileStates(p);
	    /* Ensure clean state, this could get called more than once. */
	    rpmfsResetActions(fs);
	    if (rpmteType(p) == TR_ADDED) {
		skipInstallFiles(ts, files, fs);
	    } else {
		skipEraseFiles(ts, files, fs);
	    }
	}
	rpmfilesFree(files);
    }
    rpmtsiFree(pi);

    /* Open rpmdb & enter chroot for fingerprinting if necessary */
    if (rpmdbOpenAll(ts->rdb) || rpmChrootIn()) {
	rc = -1;
	goto exit;
    }
    
    rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, tsmem->orderCount);
    /* Add fingerprint for each file not skipped. */
    fpCachePopulate(fpc, ts, fileCount);
    /* check against files in the rpmdb */
    checkInstalledFiles(ts, fileCount, fpc);

    dbhome = rpmdbHome(rpmtsGetRdb(ts));
    /* If we can't stat, ignore db growth. Probably not right but... */
    if (dbhome && stat(dbhome, &dbstat))
	dbhome = NULL;

    pi = rpmtsiInit(ts);
    while ((p = rpmtsiNext(pi, 0)) != NULL) {
	rpmfiles files = rpmteFiles(p);;
	if (files == 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. */
	handleOverlappedFiles(ts, fpc, p, files);

	/* Check added package has sufficient space on each partition used. */
	if (rpmteType(p) == TR_ADDED) {
	    /*
	     * Try to estimate space needed for rpmdb growth: guess that the
	     * db grows 4 times the header size (indexes and all).
	     */
	    if (dbhome) {
		int64_t hsize = rpmteHeaderSize(p) * 4;
		rpmtsUpdateDSI(ts, dbstat.st_dev, dbhome,
			       hsize, 0, 0, FA_CREATE);
	    }

	    rpmtsCheckDSIProblems(ts, p);
	}
	(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
	rpmfilesFree(files);
    }
    rpmtsiFree(pi);
    rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, tsmem->orderCount);

    /* return from chroot if done earlier */
    if (rpmChrootOut())
	rc = -1;

    /* On actual transaction, file info sets are not needed after this */
    if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))) {
	pi = rpmtsiInit(ts);
	while ((p = rpmtsiNext(pi, 0)) != NULL) {
	    rpmteCleanFiles(p);
	}
	rpmtsiFree(pi);
    }

exit:
    fpCacheFree(fpc);
    rpmtsFreeDSI(ts);
    return rc;
}
示例#9
0
文件: fsm.c 项目: nforro/rpm
/** \ingroup payload
 * Create directory name iterator.
 * @param fi		file info set
 * @param fs		file state set
 * @param reverse	traverse directory names in reverse order?
 * @return		directory name iterator
 */
static DNLI_t dnlInitIterator(rpmfiles fi, rpmfs fs, int reverse)
{
    DNLI_t dnli;
    int i, j;
    int dc;

    if (fi == NULL)
	return NULL;
    dc = rpmfilesDC(fi);
    dnli = xcalloc(1, sizeof(*dnli));
    dnli->fi = fi;
    dnli->reverse = reverse;
    dnli->i = (reverse ? dc : 0);

    if (dc) {
	dnli->active = xcalloc(dc, sizeof(*dnli->active));
	int fc = rpmfilesFC(fi);

	/* Identify parent directories not skipped. */
	for (i = 0; i < fc; i++)
            if (!XFA_SKIPPING(rpmfsGetAction(fs, i)))
		dnli->active[rpmfilesDI(fi, i)] = 1;

	/* Exclude parent directories that are explicitly included. */
	for (i = 0; i < fc; i++) {
	    int dil;
	    size_t dnlen, bnlen;

	    if (!S_ISDIR(rpmfilesFMode(fi, i)))
		continue;

	    dil = rpmfilesDI(fi, i);
	    dnlen = strlen(rpmfilesDN(fi, dil));
	    bnlen = strlen(rpmfilesBN(fi, i));

	    for (j = 0; j < dc; j++) {
		const char * dnl;
		size_t jlen;

		if (!dnli->active[j] || j == dil)
		    continue;
		dnl = rpmfilesDN(fi, j);
		jlen = strlen(dnl);
		if (jlen != (dnlen+bnlen+1))
		    continue;
		if (!rstreqn(dnl, rpmfilesDN(fi, dil), dnlen))
		    continue;
		if (!rstreqn(dnl+dnlen, rpmfilesBN(fi, i), bnlen))
		    continue;
		if (dnl[dnlen+bnlen] != '/' || dnl[dnlen+bnlen+1] != '\0')
		    continue;
		/* This directory is included in the package. */
		dnli->active[j] = 0;
		break;
	    }
	}

	/* Print only once per package. */
	if (!reverse) {
	    j = 0;
	    for (i = 0; i < dc; i++) {
		if (!dnli->active[i]) continue;
		if (j == 0) {
		    j = 1;
		    rpmlog(RPMLOG_DEBUG,
	"========== Directories not explicitly included in package:\n");
		}
		rpmlog(RPMLOG_DEBUG, "%10d %s\n", i, rpmfilesDN(fi, i));
	    }
	    if (j)
		rpmlog(RPMLOG_DEBUG, "==========\n");
	}
    }
    return dnli;
}