Пример #1
0
/**
 * Print package size (debug purposes only)
 * @param fd			package file handle
 * @param sigh			signature header
 */
static void printSize(FD_t fd, Header sigh)
{
    struct stat st;
    int fdno = Fileno(fd);
    size_t siglen = headerSizeof(sigh, HEADER_MAGIC_YES);
    size_t pad = (8 - (siglen % 8)) % 8; /* 8-byte pad */
    struct rpmtd_s sizetag;
    rpm_loff_t datalen = 0;

    /* Print package component sizes. */
    if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) {
	rpm_loff_t *tsize = rpmtdGetUint64(&sizetag);
	datalen = (tsize) ? *tsize : 0;
    } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) {
	rpm_off_t *tsize = rpmtdGetUint32(&sizetag);
	datalen = (tsize) ? *tsize : 0;
    }
    rpmtdFreeData(&sizetag);

    rpmlog(RPMLOG_DEBUG,
		"Expected size: %12" PRIu64 \
		" = lead(%d)+sigs(%zd)+pad(%zd)+data(%" PRIu64 ")\n",
		RPMLEAD_SIZE+siglen+pad+datalen,
		RPMLEAD_SIZE, siglen, pad, datalen);

    if (fstat(fdno, &st) == 0) {
	rpmlog(RPMLOG_DEBUG,
		"  Actual size: %12" PRIu64 "\n", (rpm_loff_t) st.st_size);
    }
}
Пример #2
0
/*
 * Convert single tag data item to python object of suitable type
 */
PyObject * rpmtd_ItemAsPyobj(rpmtd td)
{
    PyObject *res = NULL;
    char *str = NULL;

    switch (rpmtdType(td)) {
    case RPM_STRING_TYPE:
    case RPM_I18NSTRING_TYPE:
    case RPM_STRING_ARRAY_TYPE:
	res = PyString_FromString(rpmtdGetString(td));
	break;
    case RPM_INT64_TYPE:
	res = PyLong_FromLongLong(*rpmtdGetUint64(td));
	break;
    case RPM_INT32_TYPE:
	res = PyInt_FromLong(*rpmtdGetUint32(td));
	break;
    case RPM_INT16_TYPE:
	res = PyInt_FromLong(*rpmtdGetUint16(td));
	break;
    case RPM_BIN_TYPE:
	str = rpmtdFormat(td, RPMTD_FORMAT_STRING, NULL);
	res = PyString_FromString(str);
	free(str);
	break;
    default:
	PyErr_SetString(PyExc_KeyError, "unhandled data type");
	break;
    }
    return res;
}
Пример #3
0
/**
 * Retrieve trigger type info.
 * @param h		header
 * @retval td		tag data container
 * @return		1 on success
 */
static int triggertypeTag(Header h, rpmtd td, headerGetFlags hgflags)
{
    int i;
    char ** conds;
    struct rpmtd_s indices, flags, scripts;

    if (!headerGet(h, RPMTAG_TRIGGERINDEX, &indices, HEADERGET_MINMEM)) {
	return 0;
    }

    headerGet(h, RPMTAG_TRIGGERFLAGS, &flags, HEADERGET_MINMEM);
    headerGet(h, RPMTAG_TRIGGERSCRIPTS, &scripts, HEADERGET_MINMEM);

    td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED;
    td->count = rpmtdCount(&scripts);
    td->data = conds = xmalloc(sizeof(*conds) * td->count);
    td->type = RPM_STRING_ARRAY_TYPE;

    while ((i = rpmtdNext(&scripts)) >= 0) {
	rpm_flag_t *flag;
	rpmtdInit(&indices); rpmtdInit(&flags);

	while (rpmtdNext(&indices) >= 0 && rpmtdNext(&flags) >= 0) {
	    if (*rpmtdGetUint32(&indices) != i) 
		continue;

	    flag = rpmtdGetUint32(&flags);
	    if (*flag & RPMSENSE_TRIGGERPREIN)
		conds[i] = xstrdup("prein");
	    else if (*flag & RPMSENSE_TRIGGERIN)
		conds[i] = xstrdup("in");
	    else if (*flag & RPMSENSE_TRIGGERUN)
		conds[i] = xstrdup("un");
	    else if (*flag & RPMSENSE_TRIGGERPOSTUN)
		conds[i] = xstrdup("postun");
	    else
		conds[i] = xstrdup("");
	    break;
	}
    }
    rpmtdFreeData(&indices);
    rpmtdFreeData(&flags);
    rpmtdFreeData(&scripts);

    return 1;
}
Пример #4
0
uint32_t *rpmtdNextUint32(rpmtd td)
{
    assert(td != NULL);
    uint32_t *res = NULL;
    if (rpmtdNext(td) >= 0) {
	res = rpmtdGetUint32(td);
    }
    return res;
}
Пример #5
0
void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te)
{
    rpmdbMatchIterator mi;
    rpmdbIndexIterator ii;
    Header trigH;
    const void *key;
    size_t keylen;
    rpmfiles files;
    rpmds rpmdsTriggers;
    rpmds rpmdsTrigger;
    int tix = 0;

    ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMDBI_TRANSFILETRIGGERNAME);
    mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_PACKAGES);
    files = rpmteFiles(te);

    /* Iterate over file triggers in rpmdb */
    while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) {
	char pfx[keylen + 1];
	memcpy(pfx, key, keylen);
	pfx[keylen] = '\0';
	/* Check if file trigger matches any file in this te */
	rpmfi fi = rpmfilesFindPrefix(files, pfx);
	if (rpmfiFC(fi) > 0) {
	    /* If yes then store it */
	    rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii),
				rpmdbIndexIteratorNumPkgs(ii));
	}
	rpmfiFree(fi);
    }
    rpmdbIndexIteratorFree(ii);

    if (rpmdbGetIteratorCount(mi)) {
	/* Filter triggers and save only trans postun triggers into ts */
	while((trigH = rpmdbNextIterator(mi)) != NULL) {
	    rpmdsTriggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0);
	    while ((rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, tix))) {
		if ((rpmdsNext(rpmdsTrigger) >= 0) &&
		    (rpmdsFlags(rpmdsTrigger) & RPMSENSE_TRIGGERPOSTUN)) {
		    struct rpmtd_s priorities;

		    headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES,
				&priorities, HEADERGET_MINMEM);
		    rpmtdSetIndex(&priorities, tix);
		    rpmtriggersAdd(ts->trigs2run, rpmdbGetIteratorOffset(mi),
				    tix, *rpmtdGetUint32(&priorities));
		}
		rpmdsFree(rpmdsTrigger);
		tix++;
	    }
	    rpmdsFree(rpmdsTriggers);
	}
    }
    rpmdbFreeIterator(mi);
}
Пример #6
0
static int NEVRA(Header h, const char **np,
		 uint32_t **ep, const char **vp, const char **rp,
		 const char **ap)
{
    if (np) *np = headerGetString(h, RPMTAG_NAME);
    if (vp) *vp = headerGetString(h, RPMTAG_VERSION);
    if (rp) *rp = headerGetString(h, RPMTAG_RELEASE);
    if (ap) *ap = headerGetString(h, RPMTAG_ARCH);
    if (ep) {
	struct rpmtd_s td;
	headerGet(h, RPMTAG_EPOCH, &td, HEADERGET_DEFAULT);
	*ep = rpmtdGetUint32(&td);
    }
    return 0;
}
Пример #7
0
rpmRC runImmedFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
			    rpmscriptTriggerModes tm, int priorityClass)
{
    int nerrors = 0;
    int triggersCount, i;
    Header trigH = rpmteHeader(te);
    struct rpmtd_s priorities;
    rpmTagVal priorityTag;
    rpmtriggers triggers;

    if (tm == RPMSCRIPT_FILETRIGGER) {
	priorityTag = RPMTAG_FILETRIGGERPRIORITIES;
    } else {
	priorityTag = RPMTAG_TRANSFILETRIGGERPRIORITIES;
    }
    headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM);

    triggersCount = rpmtdCount(&priorities);
    triggers = rpmtriggersCreate(triggersCount);

    for (i = 0; i < triggersCount; i++) {
	rpmtdSetIndex(&priorities, i);
	/* Offset is not important, all triggers are from the same package */
	rpmtriggersAdd(triggers, 0, i, *rpmtdGetUint32(&priorities));
    }

    /* Sort triggers by priority, offset, trigger index */
    rpmtriggersSortAndUniq(triggers);

    for (i = 0; i < triggersCount; i++) {
	if (priorityClass == 1) {
	    if (triggers->triggerInfo[i].priority < TRIGGER_PRIORITY_BOUND)
		continue;
	} else if (priorityClass == 2) {
	    if (triggers->triggerInfo[i].priority >= TRIGGER_PRIORITY_BOUND)
		continue;
	}

	nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 2,
					    triggers->triggerInfo[i].tix);
    }
    rpmtriggersFree(triggers);
    headerFree(trigH);

    return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL;
}
Пример #8
0
/**
 * Retrieve trigger info.
 * @param mode		type of trigger (see tMode_e)
 * @param h		header
 * @retval td		tag data container
 * @param hgflags	header get flags
 * @return		1 on success
 */
static int triggercondsTagFor(tMode mode, Header h, rpmtd td,
				headerGetFlags hgflags)
{
    uint32_t * indices;
    int i, j;
    char ** conds;
    struct rpmtd_s nametd, indextd, flagtd, versiontd, scripttd;
    int hgeflags = HEADERGET_MINMEM;
    rpmTagVal triggername, triggerindex, triggerflags;
    rpmTagVal triggerversion, triggerscripts;

    switch (mode) {
	case NORMALTRIGGER:
	    triggername = RPMTAG_TRIGGERNAME;
	    triggerindex = RPMTAG_TRIGGERINDEX;
	    triggerflags = RPMTAG_TRIGGERFLAGS;
	    triggerversion = RPMTAG_TRIGGERVERSION;
	    triggerscripts = RPMTAG_TRIGGERSCRIPTS;
	    break;
	case FILETRIGGER:
	    triggername = RPMTAG_FILETRIGGERNAME;
	    triggerindex = RPMTAG_FILETRIGGERINDEX;
	    triggerflags = RPMTAG_FILETRIGGERFLAGS;
	    triggerversion = RPMTAG_FILETRIGGERVERSION;
	    triggerscripts = RPMTAG_FILETRIGGERSCRIPTS;
	    break;
	case TRANSFILETRIGGER:
	    triggername = RPMTAG_TRANSFILETRIGGERNAME;
	    triggerindex = RPMTAG_TRANSFILETRIGGERINDEX;
	    triggerflags = RPMTAG_TRANSFILETRIGGERFLAGS;
	    triggerversion = RPMTAG_TRANSFILETRIGGERVERSION;
	    triggerscripts = RPMTAG_TRANSFILETRIGGERSCRIPTS;
	    break;
	default:
	    return 0;
    }

    if (!headerGet(h, triggername, &nametd, hgeflags)) {
	return 0;
    }

    headerGet(h, triggerindex, &indextd, hgeflags);
    headerGet(h, triggerflags, &flagtd, hgeflags);
    headerGet(h, triggerversion, &versiontd, hgeflags);
    headerGet(h, triggerscripts, &scripttd, hgeflags);

    td->type = RPM_STRING_ARRAY_TYPE;
    td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED;
    td->data = conds = xmalloc(sizeof(*conds) * rpmtdCount(&scripttd));
    td->count = rpmtdCount(&scripttd);

    indices = indextd.data;

    while ((i = rpmtdNext(&scripttd)) >= 0) {
	rpm_flag_t *flag;
	char *flagStr, *item;
	ARGV_t items = NULL;

	rpmtdInit(&nametd); rpmtdInit(&flagtd); rpmtdInit(&versiontd);
	while ((j = rpmtdNext(&nametd)) >= 0) {
	    /* flag and version arrays match name array size always */
	    rpmtdNext(&flagtd); rpmtdNext(&versiontd);

	    if (indices[j] != i)
		continue;

	    flag = rpmtdGetUint32(&flagtd);
	    if (flag && *flag & RPMSENSE_SENSEMASK) {
		flagStr = rpmtdFormat(&flagtd, RPMTD_FORMAT_DEPFLAGS, NULL);
		rasprintf(&item, "%s %s %s", rpmtdGetString(&nametd),
					     flagStr,
					     rpmtdGetString(&versiontd));
		free(flagStr);
	    } else {
		item = xstrdup(rpmtdGetString(&nametd));
	    }

	    argvAdd(&items, item);
	    free(item);
	}

	conds[i] = argvJoin(items, ", ");
	argvFree(items);
    }

    rpmtdFreeData(&nametd);
    rpmtdFreeData(&versiontd);
    rpmtdFreeData(&flagtd);
    rpmtdFreeData(&indextd);
    rpmtdFreeData(&scripttd);
    return 1;
}
Пример #9
0
rpmfi rpmfiNew(const rpmts ts, Header h, rpmTag tagN, rpmfiFlags flags)
{
    rpmfi fi = NULL;
    rpm_loff_t *asize = NULL;
    unsigned char * t;
    int isBuild, isSource;
    struct rpmtd_s fdigests, digalgo;
    struct rpmtd_s td;
    headerGetFlags scareFlags = (flags & RPMFI_KEEPHEADER) ? 
				HEADERGET_MINMEM : HEADERGET_ALLOC;
    headerGetFlags defFlags = HEADERGET_ALLOC;

    fi = xcalloc(1, sizeof(*fi));
    if (fi == NULL)	/* XXX can't happen */
	goto exit;

    fi->magic = RPMFIMAGIC;
    fi->i = -1;

    fi->fiflags = flags;
    fi->scareFlags = scareFlags;

    if (headerGet(h, RPMTAG_LONGARCHIVESIZE, &td, HEADERGET_EXT)) {
	asize = rpmtdGetUint64(&td);
    }
    /* 0 means unknown */
    fi->archiveSize = asize ? *asize : 0;
    rpmtdFreeData(&td);
    
    /* Archive size is not set when this gets called from build */
    isBuild = (asize == NULL);
    isSource = headerIsSource(h);
    if (isBuild) fi->fiflags |= RPMFI_ISBUILD;
    if (isSource) fi->fiflags |= RPMFI_ISSOURCE;

    _hgfi(h, RPMTAG_BASENAMES, &td, defFlags, fi->bnl);
    fi->fc = rpmtdCount(&td);
    if (fi->fc == 0) {
	goto exit;
    }

    _hgfi(h, RPMTAG_DIRNAMES, &td, defFlags, fi->dnl);
    fi->dc = rpmtdCount(&td);
    _hgfi(h, RPMTAG_DIRINDEXES, &td, scareFlags, fi->dil);
    if (!(flags & RPMFI_NOFILEMODES))
	_hgfi(h, RPMTAG_FILEMODES, &td, scareFlags, fi->fmodes);
    if (!(flags & RPMFI_NOFILEFLAGS))
	_hgfi(h, RPMTAG_FILEFLAGS, &td, scareFlags, fi->fflags);
    if (!(flags & RPMFI_NOFILEVERIFYFLAGS))
	_hgfi(h, RPMTAG_FILEVERIFYFLAGS, &td, scareFlags, fi->vflags);
    if (!(flags & RPMFI_NOFILESIZES))
	_hgfi(h, RPMTAG_FILESIZES, &td, scareFlags, fi->fsizes);

    if (!(flags & RPMFI_NOFILECOLORS))
	_hgfi(h, RPMTAG_FILECOLORS, &td, scareFlags, fi->fcolors);

    if (!(flags & RPMFI_NOFILECLASS)) {
	_hgfi(h, RPMTAG_CLASSDICT, &td, scareFlags, fi->cdict);
	fi->ncdict = rpmtdCount(&td);
	_hgfi(h, RPMTAG_FILECLASS, &td, scareFlags, fi->fcdictx);
    }
    if (!(flags & RPMFI_NOFILEDEPS)) {
	_hgfi(h, RPMTAG_DEPENDSDICT, &td, scareFlags, fi->ddict);
	fi->nddict = rpmtdCount(&td);
	_hgfi(h, RPMTAG_FILEDEPENDSX, &td, scareFlags, fi->fddictx);
	_hgfi(h, RPMTAG_FILEDEPENDSN, &td, scareFlags, fi->fddictn);
    }

    if (!(flags & RPMFI_NOFILESTATES))
	_hgfi(h, RPMTAG_FILESTATES, &td, defFlags, fi->fstates);

    if (!(flags & RPMFI_NOFILECAPS) && headerIsEntry(h, RPMTAG_FILECAPS)) {
	fi->fcapcache = strcacheNew();
	fi->fcaps = cacheTag(fi->fcapcache, h, RPMTAG_FILECAPS);
    }

    if (!(flags & RPMFI_NOFILELINKTOS)) {
	fi->flinkcache = strcacheNew();
	fi->flinks = cacheTag(fi->flinkcache, h, RPMTAG_FILELINKTOS);
    }
    /* FILELANGS are only interesting when installing */
    if ((headerGetInstance(h) == 0) && !(flags & RPMFI_NOFILELANGS))
	fi->flangs = cacheTag(langcache, h, RPMTAG_FILELANGS);

    /* See if the package has non-md5 file digests */
    fi->digestalgo = PGPHASHALGO_MD5;
    if (headerGet(h, RPMTAG_FILEDIGESTALGO, &digalgo, HEADERGET_MINMEM)) {
	pgpHashAlgo *algo = rpmtdGetUint32(&digalgo);
	/* Hmm, what to do with unknown digest algorithms? */
	if (algo && rpmDigestLength(*algo) != 0) {
	    fi->digestalgo = *algo;
	}
    }

    fi->digests = NULL;
    /* grab hex digests from header and store in binary format */
    if (!(flags & RPMFI_NOFILEDIGESTS) &&
	headerGet(h, RPMTAG_FILEDIGESTS, &fdigests, HEADERGET_MINMEM)) {
	const char *fdigest;
	size_t diglen = rpmDigestLength(fi->digestalgo);
	fi->digests = t = xmalloc(rpmtdCount(&fdigests) * diglen);

	while ((fdigest = rpmtdNextString(&fdigests))) {
	    if (!(fdigest && *fdigest != '\0')) {
		memset(t, 0, diglen);
		t += diglen;
		continue;
	    }
	    for (int j = 0; j < diglen; j++, t++, fdigest += 2)
		*t = (rnibble(fdigest[0]) << 4) | rnibble(fdigest[1]);
	}
	rpmtdFreeData(&fdigests);
    }

    /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes */
    if (!(flags & RPMFI_NOFILEMTIMES))
	_hgfi(h, RPMTAG_FILEMTIMES, &td, scareFlags, fi->fmtimes);
    if (!(flags & RPMFI_NOFILERDEVS))
	_hgfi(h, RPMTAG_FILERDEVS, &td, scareFlags, fi->frdevs);
    if (!(flags & RPMFI_NOFILEINODES))
	_hgfi(h, RPMTAG_FILEINODES, &td, scareFlags, fi->finodes);

    if (!(flags & RPMFI_NOFILEUSER)) 
	fi->fuser = cacheTag(ugcache, h, RPMTAG_FILEUSERNAME);
    if (!(flags & RPMFI_NOFILEGROUP)) 
	fi->fgroup = cacheTag(ugcache, h, RPMTAG_FILEGROUPNAME);

    /* lazily alloced from rpmfiFN() */
    fi->fn = NULL;

exit:
if (_rpmfi_debug < 0)
fprintf(stderr, "*** fi %p\t[%d]\n", fi, (fi ? fi->fc : 0));

    if (fi != NULL) {
	fi->h = (fi->fiflags & RPMFI_KEEPHEADER) ? headerLink(h) : NULL;
    }

    /* FIX: rpmfi null annotations */
    return rpmfiLink(fi, __FUNCTION__);
}
Пример #10
0
/* 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
void checkInstalledFiles(rpmts ts, uint64_t fileCount, fingerPrintCache fpc)
{
    tsMembers tsmem = rpmtsMembers(ts);
    rpmte p;
    rpmfiles fi;
    rpmfs fs;
    int j;
    unsigned int fileNum;

    rpmdbMatchIterator mi;
    Header h, newheader;

    rpmlog(RPMLOG_DEBUG, "computing file dispositions\n");

    mi = rpmFindBaseNamesInDB(ts, fileCount);

    /* 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 *fpp = NULL;
	unsigned int installedPkg;
	int beingRemoved = 0;
	rpmfiles otherFi = NULL;
	rpmte *removedPkg = NULL;

	/* Is this package being removed? */
	installedPkg = rpmdbGetIteratorOffset(mi);
	if (packageHashGetEntry(tsmem->removedPackages, installedPkg,
				&removedPkg, NULL, NULL)) {
	    beingRemoved = 1;
	    otherFi = rpmteFiles(removedPkg[0]);
	}

	h = headerLink(h);
	/* For packages being removed we can use its rpmfi to avoid all this */
	if (!beingRemoved) {
	    headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags);
	    headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags);
	    headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags);
	    headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags);
	}

	/* loop over all interesting files in that package */
	do {
	    int fpIx;
	    struct rpmffi_s * recs;
	    int numRecs;
	    const char * dirName;
	    const char * baseName;

	    /* lookup finger print for this file */
	    fileNum = rpmdbGetIteratorFileNum(mi);
	    if (!beingRemoved) {
		rpmtdSetIndex(&bnames, fileNum);
		rpmtdSetIndex(&dindexes, fileNum);
		rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes));
		rpmtdSetIndex(&ostates, fileNum);

		dirName = rpmtdGetString(&dnames);
		baseName = rpmtdGetString(&bnames);

		fpLookup(fpc, dirName, baseName, &fpp);
		fpIx = 0;
	    } else {
		fpp = rpmfilesFps(otherFi);
		fpIx = fileNum;
	    }

	    /* search for files in the transaction with same finger print */
	    fpCacheGetByFp(fpc, fpp, fpIx, &recs, &numRecs);

	    for (j = 0; j < numRecs; j++) {
	        p = recs[j].p;
		fi = rpmteFiles(p);
		fs = rpmteGetFileStates(p);

		/* Determine the fate of each file. */
		switch (rpmteType(p)) {
		case TR_ADDED:
		    if (!otherFi) {
			/* XXX What to do if this fails? */
		        otherFi = rpmfilesNew(NULL, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER);
		    }
		    handleInstInstalledFile(ts, p, fi, recs[j].fileno,
					    h, otherFi, fileNum, beingRemoved);
		    break;
		case TR_REMOVED:
		    if (!beingRemoved) {
			if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL)
			    rpmfsSetAction(fs, recs[j].fileno, FA_SKIP);
		    }
		    break;
		}
		rpmfilesFree(fi);
	    }

	    newheader = rpmdbNextIterator(mi);

	} while (newheader==h);

	otherFi = rpmfilesFree(otherFi);
	if (!beingRemoved) {
	    rpmtdFreeData(&ostates);
	    rpmtdFreeData(&bnames);
	    rpmtdFreeData(&dnames);
	    rpmtdFreeData(&dindexes);
	    free(fpp);
	}
	headerFree(h);
	h = newheader;
    }

    rpmdbFreeIterator(mi);
}
Пример #11
0
rpmfi rpmfiNew(const rpmts ts, Header h, rpmTagVal tagN, rpmfiFlags flags)
{
    rpmfi fi = xcalloc(1, sizeof(*fi)); 
    unsigned char * t;
    struct rpmtd_s fdigests, digalgo;
    struct rpmtd_s td;
    headerGetFlags scareFlags = (flags & RPMFI_KEEPHEADER) ? 
				HEADERGET_MINMEM : HEADERGET_ALLOC;
    headerGetFlags defFlags = HEADERGET_ALLOC;

    fi->magic = RPMFIMAGIC;
    fi->i = -1;

    fi->fiflags = flags;

    _hgfi(h, RPMTAG_BASENAMES, &td, defFlags, fi->bnl);
    fi->fc = rpmtdCount(&td);
    if (fi->fc == 0) {
	goto exit;
    }

    _hgfi(h, RPMTAG_DIRNAMES, &td, defFlags, fi->dnl);
    fi->dc = rpmtdCount(&td);
    _hgfi(h, RPMTAG_DIRINDEXES, &td, scareFlags, fi->dil);

    /* Is our filename triplet sane? */
    if (fi->dc == 0 || fi->dc > fi->fc || rpmtdCount(&td) != fi->fc)
	goto errxit;

    for (rpm_count_t i = 0; i < fi->fc; i++) {
	if (fi->dil[i] >= fi->fc)
	    goto errxit;
    }

    /* XXX TODO: all these should be sanity checked, ugh... */
    if (!(flags & RPMFI_NOFILEMODES))
	_hgfi(h, RPMTAG_FILEMODES, &td, scareFlags, fi->fmodes);
    if (!(flags & RPMFI_NOFILEFLAGS))
	_hgfi(h, RPMTAG_FILEFLAGS, &td, scareFlags, fi->fflags);
    if (!(flags & RPMFI_NOFILEVERIFYFLAGS))
	_hgfi(h, RPMTAG_FILEVERIFYFLAGS, &td, scareFlags, fi->vflags);
    if (!(flags & RPMFI_NOFILESIZES))
	_hgfi(h, RPMTAG_FILESIZES, &td, scareFlags, fi->fsizes);

    if (!(flags & RPMFI_NOFILECOLORS))
	_hgfi(h, RPMTAG_FILECOLORS, &td, scareFlags, fi->fcolors);

    if (!(flags & RPMFI_NOFILECLASS)) {
	_hgfi(h, RPMTAG_CLASSDICT, &td, scareFlags, fi->cdict);
	fi->ncdict = rpmtdCount(&td);
	_hgfi(h, RPMTAG_FILECLASS, &td, scareFlags, fi->fcdictx);
    }
    if (!(flags & RPMFI_NOFILEDEPS)) {
	_hgfi(h, RPMTAG_DEPENDSDICT, &td, scareFlags, fi->ddict);
	fi->nddict = rpmtdCount(&td);
	_hgfi(h, RPMTAG_FILEDEPENDSX, &td, scareFlags, fi->fddictx);
	_hgfi(h, RPMTAG_FILEDEPENDSN, &td, scareFlags, fi->fddictn);
    }

    if (!(flags & RPMFI_NOFILESTATES))
	_hgfi(h, RPMTAG_FILESTATES, &td, defFlags, fi->fstates);

    if (!(flags & RPMFI_NOFILECAPS) && headerIsEntry(h, RPMTAG_FILECAPS)) {
	fi->fcapcache = strcacheNew();
	fi->fcaps = cacheTag(fi->fcapcache, h, RPMTAG_FILECAPS);
    }

    if (!(flags & RPMFI_NOFILELINKTOS)) {
	fi->flinkcache = strcacheNew();
	fi->flinks = cacheTag(fi->flinkcache, h, RPMTAG_FILELINKTOS);
    }
    /* FILELANGS are only interesting when installing */
    if ((headerGetInstance(h) == 0) && !(flags & RPMFI_NOFILELANGS))
	fi->flangs = cacheTag(langcache, h, RPMTAG_FILELANGS);

    /* See if the package has non-md5 file digests */
    fi->digestalgo = PGPHASHALGO_MD5;
    if (headerGet(h, RPMTAG_FILEDIGESTALGO, &digalgo, HEADERGET_MINMEM)) {
	uint32_t *algo = rpmtdGetUint32(&digalgo);
	/* Hmm, what to do with unknown digest algorithms? */
	if (algo && rpmDigestLength(*algo) != 0) {
	    fi->digestalgo = *algo;
	}
    }

    fi->digests = NULL;
    /* grab hex digests from header and store in binary format */
    if (!(flags & RPMFI_NOFILEDIGESTS) &&
	headerGet(h, RPMTAG_FILEDIGESTS, &fdigests, HEADERGET_MINMEM)) {
	const char *fdigest;
	size_t diglen = rpmDigestLength(fi->digestalgo);
	fi->digests = t = xmalloc(rpmtdCount(&fdigests) * diglen);

	while ((fdigest = rpmtdNextString(&fdigests))) {
	    if (!(fdigest && *fdigest != '\0')) {
		memset(t, 0, diglen);
		t += diglen;
		continue;
	    }
	    for (int j = 0; j < diglen; j++, t++, fdigest += 2)
		*t = (rnibble(fdigest[0]) << 4) | rnibble(fdigest[1]);
	}
	rpmtdFreeData(&fdigests);
    }

    /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes */
    if (!(flags & RPMFI_NOFILEMTIMES))
	_hgfi(h, RPMTAG_FILEMTIMES, &td, scareFlags, fi->fmtimes);
    if (!(flags & RPMFI_NOFILERDEVS))
	_hgfi(h, RPMTAG_FILERDEVS, &td, scareFlags, fi->frdevs);
    if (!(flags & RPMFI_NOFILEINODES))
	_hgfi(h, RPMTAG_FILEINODES, &td, scareFlags, fi->finodes);

    if (!(flags & RPMFI_NOFILEUSER)) 
	fi->fuser = cacheTag(ugcache, h, RPMTAG_FILEUSERNAME);
    if (!(flags & RPMFI_NOFILEGROUP)) 
	fi->fgroup = cacheTag(ugcache, h, RPMTAG_FILEGROUPNAME);

    /* lazily alloced from rpmfiFN() */
    fi->fn = NULL;

exit:

    if (fi != NULL) {
	fi->h = (fi->fiflags & RPMFI_KEEPHEADER) ? headerLink(h) : NULL;
    }

    /* FIX: rpmfi null annotations */
    return rpmfiLink(fi);

errxit:
    rpmfiFree(fi);
    return NULL;
}
Пример #12
0
/* 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
void checkInstalledFiles(rpmts ts, fingerPrintCache fpc)
{
    rpmps ps;
    rpmte p;
    rpmfi fi;
    rpmfs fs;
    rpmfi otherFi=NULL;
    int j;
    int xx;
    unsigned int fileNum;
    const char * oldDir;

    rpmdbMatchIterator mi;
    Header h, newheader;

    int beingRemoved;

    rpmlog(RPMLOG_DEBUG, "computing file dispositions\n");

    mi = rpmFindBaseNamesInDB(ts);

    /* For all installed headers with matching basename's ... */
    if (mi == NULL)
	 return;

    if (rpmdbGetIteratorCount(mi) == 0) {
	mi = rpmdbFreeIterator(mi);
	return;
    }

    ps = rpmtsProblems(ts);

    /* 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);
	beingRemoved = 0;
	if (ts->removedPackages != NULL)
	for (j = 0; j < ts->numRemovedPackages; j++) {
	    if (ts->removedPackages[j] != installedPkg)
	        continue;
	    beingRemoved = 1;
	    break;
	}

	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;
	/* loop over all interesting files in that package */
	do {
	    int gotRecs;
	    struct rpmffi_s * recs;
	    int numRecs;
	    const char * dirName;
	    const char * baseName;

	    fileNum = rpmdbGetIteratorFileNum(mi);
	    rpmtdSetIndex(&bnames, fileNum);
	    rpmtdSetIndex(&dindexes, fileNum);
	    rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes));
	    rpmtdSetIndex(&ostates, fileNum);

	    dirName = rpmtdGetString(&dnames);
	    baseName = rpmtdGetString(&bnames);

	    /* lookup finger print for this file */
	    if ( dirName == oldDir) {
	        /* directory is the same as last round */
	        fp.baseName = baseName;
	    } else {
	        fp = fpLookup(fpc, dirName, baseName, 1);
		oldDir = dirName;
	    }
	    /* search for files in the transaction with same finger print */
	    gotRecs = rpmFpHashGetEntry(ts->ht, &fp, &recs, &numRecs, NULL);

	    for (j=0; (j<numRecs)&&gotRecs; j++) {
	        p = recs[j].p;
		fi = rpmteFI(p);
		fs = rpmteGetFileStates(p);

		/* Determine the fate of each file. */
		switch (rpmteType(p)) {
		case TR_ADDED:
		    if (!otherFi) {
		        otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER);
		    }
		    rpmfiSetFX(fi, recs[j].fileno);
		    rpmfiSetFX(otherFi, fileNum);
		    xx = handleInstInstalledFile(ts, p, fi, h, otherFi, beingRemoved);
		    break;
		case TR_REMOVED:
		    if (!beingRemoved) {
		        rpmfiSetFX(fi, recs[j].fileno);
			if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL)
			    rpmfsSetAction(fs, recs[j].fileno, FA_SKIP);
		    }
		    break;
		}
	    }

	    newheader = rpmdbNextIterator(mi);

	} while (newheader==h);

	otherFi = rpmfiFree(otherFi);
	rpmtdFreeData(&ostates);
	rpmtdFreeData(&bnames);
	rpmtdFreeData(&dnames);
	rpmtdFreeData(&dindexes);
	headerFree(h);
	h = newheader;
    }

    mi = rpmdbFreeIterator(mi);
}
Пример #13
0
rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
{
    char *buf = NULL;
    int32_t block[4];
    int32_t il;
    int32_t dl;
    int32_t * ei = NULL;
    entryInfo pe;
    unsigned int nb, uc;
    struct indexEntry_s entry;
    unsigned char * dataStart;
    Header sigh = NULL;
    rpmRC rc = RPMRC_FAIL;		/* assume failure */
    int xx;
    int i;

    if (sighp)
        *sighp = NULL;

    if (sig_type != RPMSIGTYPE_HEADERSIG)
        goto exit;

    memset(block, 0, sizeof(block));
    if ((xx = Freadall(fd, block, sizeof(block))) != sizeof(block)) {
        rasprintf(&buf, _("sigh size(%d): BAD, read returned %d"),
                  (int)sizeof(block), xx);
        goto exit;
    }
    if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) {
        rasprintf(&buf, _("sigh magic: BAD"));
        goto exit;
    }
    il = ntohl(block[2]);
    if (il < 0 || il > 32) {
        rasprintf(&buf,
                  _("sigh tags: BAD, no. of tags(%d) out of range"), il);
        goto exit;
    }
    dl = ntohl(block[3]);
    if (dl < 0 || dl > 8192) {
        rasprintf(&buf,
                  _("sigh data: BAD, no. of  bytes(%d) out of range"), dl);
        goto exit;
    }

    memset(&entry, 0, sizeof(entry));

    nb = (il * sizeof(struct entryInfo_s)) + dl;
    uc = sizeof(il) + sizeof(dl) + nb;
    ei = xmalloc(uc);
    ei[0] = block[2];
    ei[1] = block[3];
    pe = (entryInfo) &ei[2];
    dataStart = (unsigned char *) (pe + il);
    if ((xx = Freadall(fd, pe, nb)) != nb) {
        rasprintf(&buf,
                  _("sigh blob(%d): BAD, read returned %d"), (int)nb, xx);
        goto exit;
    }

    /* Verify header immutable region if there is one */
    xx = headerVerifyRegion(RPMTAG_HEADERSIGNATURES,
                            &entry, il, dl, pe, dataStart,
                            NULL, NULL, &buf);
    /* Not found means a legacy V3 package with no immutable region */
    if (xx != RPMRC_OK && xx != RPMRC_NOTFOUND)
        goto exit;

    /* Sanity check signature tags */
    for (i = 1; i < il; i++) {
        xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0);
        if (xx != -1) {
            rasprintf(&buf,
                      _("sigh tag[%d]: BAD, tag %d type %d offset %d count %d"),
                      i, entry.info.tag, entry.info.type,
                      entry.info.offset, entry.info.count);
            goto exit;
        }
    }

    /* OK, blob looks sane, load the header. */
    sigh = headerImport(ei, uc, 0);
    if (sigh == NULL) {
        rasprintf(&buf, _("sigh load: BAD"));
        goto exit;
    }
    ei = NULL; /* XXX will be freed with header */

    {   size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
        size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */
        ssize_t trc;
        struct rpmtd_s sizetag;
        rpm_loff_t archSize = 0;

        /* Position at beginning of header. */
        if (pad && (trc = Freadall(fd, block, pad)) != pad) {
            rasprintf(&buf,
                      _("sigh pad(%zd): BAD, read %zd bytes"), pad, trc);
            goto exit;
        }

        /* Print package component sizes. */
        if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) {
            rpm_loff_t *tsize = rpmtdGetUint64(&sizetag);
            archSize = (tsize) ? *tsize : 0;
        } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) {
            rpm_off_t *tsize = rpmtdGetUint32(&sizetag);
            archSize = (tsize) ? *tsize : 0;
        }
        rpmtdFreeData(&sizetag);
        rc = printSize(fd, sigSize, pad, archSize);
        if (rc != RPMRC_OK) {
            rasprintf(&buf,
                      _("sigh sigSize(%zd): BAD, fstat(2) failed"), sigSize);
            goto exit;
        }
    }

exit:
    if (sighp && sigh && rc == RPMRC_OK)
        *sighp = headerLink(sigh);
    headerFree(sigh);
    free(ei);

    if (msg != NULL) {
        *msg = buf;
    } else {
        free(buf);
    }

    return rc;
}
Пример #14
0
/**
 * Retrieve trigger type info.
 * @param mode		type of trigger (see tMode_e)
 * @param h		header
 * @retval td		tag data container
 * @param hgflags	header get flags
 * @return		1 on success
 */
static int triggertypeTagFor(tMode mode, Header h, rpmtd td,
				headerGetFlags hgflags)
{
    int i;
    char ** conds;
    struct rpmtd_s indices, flags, scripts;
    rpmTagVal triggerindex, triggerflags, triggerscripts;

    switch (mode) {
	case NORMALTRIGGER:
	    triggerindex = RPMTAG_TRIGGERINDEX;
	    triggerflags = RPMTAG_TRIGGERFLAGS;
	    triggerscripts = RPMTAG_TRIGGERSCRIPTS;
	    break;
	case FILETRIGGER:
	    triggerindex = RPMTAG_FILETRIGGERINDEX;
	    triggerflags = RPMTAG_FILETRIGGERFLAGS;
	    triggerscripts = RPMTAG_FILETRIGGERSCRIPTS;
	    break;
	case TRANSFILETRIGGER:
	    triggerindex = RPMTAG_TRANSFILETRIGGERINDEX;
	    triggerflags = RPMTAG_TRANSFILETRIGGERFLAGS;
	    triggerscripts = RPMTAG_TRANSFILETRIGGERSCRIPTS;
	    break;
	default:
	   return 0;
    }

    if (!headerGet(h, triggerindex, &indices, HEADERGET_MINMEM)) {
	return 0;
    }

    headerGet(h, triggerflags, &flags, HEADERGET_MINMEM);
    headerGet(h, triggerscripts, &scripts, HEADERGET_MINMEM);

    td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED;
    td->count = rpmtdCount(&scripts);
    td->data = conds = xmalloc(sizeof(*conds) * td->count);
    td->type = RPM_STRING_ARRAY_TYPE;

    while ((i = rpmtdNext(&scripts)) >= 0) {
	rpm_flag_t *flag;
	rpmtdInit(&indices); rpmtdInit(&flags);

	while (rpmtdNext(&indices) >= 0 && rpmtdNext(&flags) >= 0) {
	    if (*rpmtdGetUint32(&indices) != i) 
		continue;

	    flag = rpmtdGetUint32(&flags);
	    if (*flag & RPMSENSE_TRIGGERPREIN)
		conds[i] = xstrdup("prein");
	    else if (*flag & RPMSENSE_TRIGGERIN)
		conds[i] = xstrdup("in");
	    else if (*flag & RPMSENSE_TRIGGERUN)
		conds[i] = xstrdup("un");
	    else if (*flag & RPMSENSE_TRIGGERPOSTUN)
		conds[i] = xstrdup("postun");
	    else
		conds[i] = xstrdup("");
	    break;
	}
    }
    rpmtdFreeData(&indices);
    rpmtdFreeData(&flags);
    rpmtdFreeData(&scripts);

    return 1;
}
Пример #15
0
rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
			rpmscriptTriggerModes tm, int priorityClass)
{
    int nerrors = 0, i;
    rpmdbIndexIterator ii;
    const void *key;
    char *pfx;
    size_t keylen;
    Header trigH;
    int (*matchFunc)(rpmts, rpmte, const char*, rpmsenseFlags sense);
    rpmTagVal priorityTag;
    rpmtriggers triggers = rpmtriggersCreate(10);

    /* Decide if we match triggers against files in te or in whole ts */
    if (tm == RPMSCRIPT_FILETRIGGER) {
	matchFunc = matchFilesInPkg;
	priorityTag = RPMTAG_FILETRIGGERPRIORITIES;
    } else {
	matchFunc = matchFilesInTran;
	priorityTag = RPMTAG_TRANSFILETRIGGERPRIORITIES;
    }

    ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), triggerDsTag(tm));

    /* Loop over all file triggers in rpmdb */
    while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) {
	pfx = xmalloc(keylen + 1);
	memcpy(pfx, key, keylen);
	pfx[keylen] = '\0';

	/* Check if file trigger is fired by any file in ts/te */
	if (matchFunc(ts, te, pfx, sense)) {
	    for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++) {
		struct rpmtd_s priorities;
		unsigned int priority;
		unsigned int offset = rpmdbIndexIteratorPkgOffset(ii, i);
		unsigned int tix = rpmdbIndexIteratorTagNum(ii, i);

		/*
		 * Don't handle transaction triggers installed in current
		 * transaction to avoid executing the same script two times.
		 * These triggers are handled in runImmedFileTriggers().
		 */
		if (tm == RPMSCRIPT_TRANSFILETRIGGER &&
		    (packageHashHasEntry(ts->members->removedPackages, offset) ||
		    packageHashHasEntry(ts->members->installedPackages, offset)))
		    continue;

		/* Get priority of trigger from header */
		trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offset);
		headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM);
		rpmtdSetIndex(&priorities, tix);
		priority = *rpmtdGetUint32(&priorities);
		headerFree(trigH);

		/* Store file trigger in array */
		rpmtriggersAdd(triggers, offset, tix, priority);
	    }
	}
	free(pfx);
    }
    rpmdbIndexIteratorFree(ii);

    /* Sort triggers by priority, offset, trigger index */
    rpmtriggersSortAndUniq(triggers);

    if (rpmChrootIn() != 0) {
	rpmtriggersFree(triggers);
	return RPMRC_FAIL;
    }

    /* Handle stored triggers */
    for (i = 0; i < triggers->count; i++) {
	if (priorityClass == 1) {
	    if (triggers->triggerInfo[i].priority < TRIGGER_PRIORITY_BOUND)
		continue;
	} else if (priorityClass == 2) {
	    if (triggers->triggerInfo[i].priority >= TRIGGER_PRIORITY_BOUND)
		continue;
	}

	trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), triggers->triggerInfo[i].hdrNum);
	if (tm == RPMSCRIPT_FILETRIGGER)
	    nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 0,
						triggers->triggerInfo[i].tix);
	else
	    nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 1,
						triggers->triggerInfo[i].tix);
	headerFree(trigH);
    }
    rpmtriggersFree(triggers);
    /* XXX an error here would require a full abort */
    (void) rpmChrootOut();

    return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL;
}
Пример #16
0
rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
{
    char *buf = NULL;
    int32_t block[4];
    int32_t il;
    int32_t dl;
    int32_t * ei = NULL;
    entryInfo pe;
    unsigned int nb, uc;
    int32_t ril = 0;
    struct indexEntry_s entry;
    struct entryInfo_s info;
    unsigned char * dataStart;
    unsigned char * dataEnd = NULL;
    Header sigh = NULL;
    rpmRC rc = RPMRC_FAIL;		/* assume failure */
    int xx;
    int i;

    if (sighp)
	*sighp = NULL;

    if (sig_type != RPMSIGTYPE_HEADERSIG)
	goto exit;

    memset(block, 0, sizeof(block));
    if ((xx = Fread(block, 1, sizeof(block), fd)) != sizeof(block)) {
	rasprintf(&buf, _("sigh size(%d): BAD, read returned %d\n"), 
		  (int)sizeof(block), xx);
	goto exit;
    }
    if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) {
	rasprintf(&buf, _("sigh magic: BAD\n"));
	goto exit;
    }
    il = ntohl(block[2]);
    if (il < 0 || il > 32) {
	rasprintf(&buf, 
		  _("sigh tags: BAD, no. of tags(%d) out of range\n"), il);
	goto exit;
    }
    dl = ntohl(block[3]);
    if (dl < 0 || dl > 8192) {
	rasprintf(&buf, 
		  _("sigh data: BAD, no. of  bytes(%d) out of range\n"), dl);
	goto exit;
    }

    memset(&entry, 0, sizeof(entry));
    memset(&info, 0, sizeof(info));

    nb = (il * sizeof(struct entryInfo_s)) + dl;
    uc = sizeof(il) + sizeof(dl) + nb;
    ei = xmalloc(uc);
    ei[0] = block[2];
    ei[1] = block[3];
    pe = (entryInfo) &ei[2];
    dataStart = (unsigned char *) (pe + il);
    if ((xx = Fread(pe, 1, nb, fd)) != nb) {
	rasprintf(&buf,
		  _("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx);
	goto exit;
    }
    
    /* Check (and convert) the 1st tag element. */
    xx = headerVerifyInfo(1, dl, pe, &entry.info, 0);
    if (xx != -1) {
	rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
		  0, entry.info.tag, entry.info.type,
		  entry.info.offset, entry.info.count);
	goto exit;
    }

    /* Is there an immutable header region tag? */
    if (entry.info.tag == RPMTAG_HEADERSIGNATURES) {
	/* Is the region tag sane? */
	if (!(entry.info.type == REGION_TAG_TYPE &&
	      entry.info.count == REGION_TAG_COUNT)) {
	    rasprintf(&buf,
		_("region tag: BAD, tag %d type %d offset %d count %d\n"),
		entry.info.tag, entry.info.type,
		entry.info.offset, entry.info.count);
	    goto exit;
	}
	
	/* Is the trailer within the data area? */
	if (entry.info.offset + REGION_TAG_COUNT > dl) {
	    rasprintf(&buf, 
		_("region offset: BAD, tag %d type %d offset %d count %d\n"),
		entry.info.tag, entry.info.type,
		entry.info.offset, entry.info.count);
	    goto exit;
	}

	/* Is there an immutable header region tag trailer? */
	dataEnd = dataStart + entry.info.offset;
	(void) memcpy(&info, dataEnd, REGION_TAG_COUNT);
	/* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */
	if (info.tag == htonl(RPMTAG_HEADERIMAGE)) {
	    rpmTagVal stag = htonl(RPMTAG_HEADERSIGNATURES);
	    info.tag = stag;
	    memcpy(dataEnd, &stag, sizeof(stag));
	}
	dataEnd += REGION_TAG_COUNT;

	xx = headerVerifyInfo(1, il * sizeof(*pe), &info, &entry.info, 1);
	if (xx != -1 ||
	    !((entry.info.tag == RPMTAG_HEADERSIGNATURES || entry.info.tag == RPMTAG_HEADERIMAGE)
	   && entry.info.type == REGION_TAG_TYPE
	   && entry.info.count == REGION_TAG_COUNT))
	{
	    rasprintf(&buf,
		_("region trailer: BAD, tag %d type %d offset %d count %d\n"),
		entry.info.tag, entry.info.type,
		entry.info.offset, entry.info.count);
	    goto exit;
	}
	memset(&info, 0, sizeof(info));

	/* Is the no. of tags in the region less than the total no. of tags? */
	ril = entry.info.offset/sizeof(*pe);
	if ((entry.info.offset % sizeof(*pe)) || ril > il) {
	    rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
	    goto exit;
	}
    }

    /* Sanity check signature tags */
    memset(&info, 0, sizeof(info));
    for (i = 1; i < il; i++) {
	xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0);
	if (xx != -1) {
	    rasprintf(&buf, 
		_("sigh tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
		i, entry.info.tag, entry.info.type,
		entry.info.offset, entry.info.count);
	    goto exit;
	}
    }

    /* OK, blob looks sane, load the header. */
    sigh = headerImport(ei, uc, 0);
    if (sigh == NULL) {
	rasprintf(&buf, _("sigh load: BAD\n"));
	goto exit;
    }

    {	size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
	size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */
	ssize_t trc;
	struct rpmtd_s sizetag;
	rpm_loff_t archSize = 0;

	/* Position at beginning of header. */
	if (pad && (trc = Fread(block, 1, pad, fd)) != pad) {
	    rasprintf(&buf,
		      _("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc);
	    goto exit;
	}

	/* Print package component sizes. */
	if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) {
	    rpm_loff_t *tsize = rpmtdGetUint64(&sizetag);
	    archSize = (tsize) ? *tsize : 0;
	} else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) {
	    rpm_off_t *tsize = rpmtdGetUint32(&sizetag);
	    archSize = (tsize) ? *tsize : 0;
	}
	rpmtdFreeData(&sizetag);
	rc = printSize(fd, sigSize, pad, archSize);
	if (rc != RPMRC_OK) {
	    rasprintf(&buf,
		   _("sigh sigSize(%zd): BAD, fstat(2) failed\n"), sigSize);
	    goto exit;
	}
    }
    ei = NULL; /* XXX will be freed with header */

exit:
    if (sighp && sigh && rc == RPMRC_OK)
	*sighp = headerLink(sigh);
    headerFree(sigh);
    free(ei);

    if (msg != NULL) {
	*msg = buf;
    } else {
	free(buf);
    }

    return rc;
}
Пример #17
0
static int rpmfiPopulate(rpmfi fi, Header h, rpmfiFlags flags)
{
    headerGetFlags scareFlags = (flags & RPMFI_KEEPHEADER) ? 
				HEADERGET_MINMEM : HEADERGET_ALLOC;
    headerGetFlags defFlags = HEADERGET_ALLOC;
    struct rpmtd_s fdigests, digalgo, td;
    unsigned char * t;

    /* XXX TODO: all these should be sanity checked, ugh... */
    if (!(flags & RPMFI_NOFILEMODES))
	_hgfi(h, RPMTAG_FILEMODES, &td, scareFlags, fi->fmodes);
    if (!(flags & RPMFI_NOFILEFLAGS))
	_hgfi(h, RPMTAG_FILEFLAGS, &td, scareFlags, fi->fflags);
    if (!(flags & RPMFI_NOFILEVERIFYFLAGS))
	_hgfi(h, RPMTAG_FILEVERIFYFLAGS, &td, scareFlags, fi->vflags);
    if (!(flags & RPMFI_NOFILESIZES)) {
	_hgfi(h, RPMTAG_FILESIZES, &td, scareFlags, fi->fsizes);
	_hgfi(h, RPMTAG_LONGFILESIZES, &td, scareFlags, fi->lfsizes);
    }
    if (!(flags & RPMFI_NOFILECOLORS))
	_hgfi(h, RPMTAG_FILECOLORS, &td, scareFlags, fi->fcolors);

    if (!(flags & RPMFI_NOFILECLASS)) {
	_hgfi(h, RPMTAG_CLASSDICT, &td, scareFlags, fi->cdict);
	fi->ncdict = rpmtdCount(&td);
	_hgfi(h, RPMTAG_FILECLASS, &td, scareFlags, fi->fcdictx);
    }
    if (!(flags & RPMFI_NOFILEDEPS)) {
	_hgfi(h, RPMTAG_DEPENDSDICT, &td, scareFlags, fi->ddict);
	fi->nddict = rpmtdCount(&td);
	_hgfi(h, RPMTAG_FILEDEPENDSX, &td, scareFlags, fi->fddictx);
	_hgfi(h, RPMTAG_FILEDEPENDSN, &td, scareFlags, fi->fddictn);
    }

    if (!(flags & RPMFI_NOFILESTATES))
	_hgfi(h, RPMTAG_FILESTATES, &td, defFlags, fi->fstates);

    if (!(flags & RPMFI_NOFILECAPS))
	_hgfi(h, RPMTAG_FILECAPS, &td, defFlags, fi->fcaps);

    if (!(flags & RPMFI_NOFILELINKTOS))
	fi->flinks = tag2pool(fi->pool, h, RPMTAG_FILELINKTOS);
    /* FILELANGS are only interesting when installing */
    if ((headerGetInstance(h) == 0) && !(flags & RPMFI_NOFILELANGS))
	fi->flangs = tag2pool(fi->pool, h, RPMTAG_FILELANGS);

    /* See if the package has non-md5 file digests */
    fi->digestalgo = PGPHASHALGO_MD5;
    if (headerGet(h, RPMTAG_FILEDIGESTALGO, &digalgo, HEADERGET_MINMEM)) {
	uint32_t *algo = rpmtdGetUint32(&digalgo);
	/* Hmm, what to do with unknown digest algorithms? */
	if (algo && rpmDigestLength(*algo) != 0) {
	    fi->digestalgo = *algo;
	}
    }

    fi->digests = NULL;
    /* grab hex digests from header and store in binary format */
    if (!(flags & RPMFI_NOFILEDIGESTS) &&
	headerGet(h, RPMTAG_FILEDIGESTS, &fdigests, HEADERGET_MINMEM)) {
	const char *fdigest;
	size_t diglen = rpmDigestLength(fi->digestalgo);
	fi->digests = t = xmalloc(rpmtdCount(&fdigests) * diglen);

	while ((fdigest = rpmtdNextString(&fdigests))) {
	    if (!(fdigest && *fdigest != '\0')) {
		memset(t, 0, diglen);
		t += diglen;
		continue;
	    }
	    for (int j = 0; j < diglen; j++, t++, fdigest += 2)
		*t = (rnibble(fdigest[0]) << 4) | rnibble(fdigest[1]);
	}
	rpmtdFreeData(&fdigests);
    }

    /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes */
    if (!(flags & RPMFI_NOFILEMTIMES))
	_hgfi(h, RPMTAG_FILEMTIMES, &td, scareFlags, fi->fmtimes);
    if (!(flags & RPMFI_NOFILERDEVS))
	_hgfi(h, RPMTAG_FILERDEVS, &td, scareFlags, fi->frdevs);
    if (!(flags & RPMFI_NOFILEINODES))
	_hgfi(h, RPMTAG_FILEINODES, &td, scareFlags, fi->finodes);

    if (!(flags & RPMFI_NOFILEUSER)) 
	fi->fuser = tag2pool(fi->pool, h, RPMTAG_FILEUSERNAME);
    if (!(flags & RPMFI_NOFILEGROUP)) 
	fi->fgroup = tag2pool(fi->pool, h, RPMTAG_FILEGROUPNAME);

    /* TODO: validate and return a real error */
    return 0;
}