Пример #1
0
void addChangelogEntry(Header h, time_t time, const char *name, const char *text)
{
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    rpmuint32_t mytime = (rpmuint32_t)time;	/* XXX convert to rpmuint32_t for header */
    int xx;

    he->tag = RPMTAG_CHANGELOGTIME;
    he->t = RPM_UINT32_TYPE;
    he->p.ui32p = &mytime;
    he->c = 1;
    he->append = 1;
    xx = headerPut(h, he, 0);
    he->append = 0;

    he->tag = RPMTAG_CHANGELOGNAME;
    he->t = RPM_STRING_ARRAY_TYPE;
    he->p.argv = &name;
    he->c = 1;
    he->append = 1;
    xx = headerPut(h, he, 0);
    he->append = 0;

    he->tag = RPMTAG_CHANGELOGTEXT;
    he->t = RPM_STRING_ARRAY_TYPE;
    he->p.argv = &text;
    he->c = 1;
    he->append = 1;
    xx = headerPut(h, he, 0);
    he->append = 0;
}
Пример #2
0
static int replaceSignature(Header sigh, sigTarget sigt_v3, sigTarget sigt_v4)
{
    int rc = -1;
    rpmtd sigtd = NULL;
    
    /* Make the cheaper v4 signature first */
    if ((sigtd = makeGPGSignature(sigh, 1, sigt_v4)) == NULL)
	goto exit;

    /* See if we already have a signature by the same key and parameters */
    if (haveSignature(sigtd, sigh)) {
	rc = 1;
	goto exit;
    }
    /* Nuke all signature tags */
    deleteSigs(sigh);

    if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
	goto exit;
    rpmtdFree(sigtd);

    /* Assume the same signature test holds for v3 signature too */
    if ((sigtd = makeGPGSignature(sigh, 0, sigt_v3)) == NULL)
	goto exit;

    if (headerPut(sigh, sigtd, HEADERPUT_DEFAULT) == 0)
	goto exit;

    rc = 0;
exit:
    rpmtdFree(sigtd);
    return rc;
}
Пример #3
0
/**
 * Add expanded build scriptlet to srpm header.
 * @param h		srpm header
 * @param progTag	interpreter tag (0 disables)
 * @param scriptTag	script tag (0 disables)
 * @param iob		script body sting buf (NULL disables)
 * @return		0 always
 */
static int initSourceHeaderScriptlet(Header h,
		rpmTag progTag, rpmTag scriptTag, rpmiob iob)
	/*@modifies h @*/
{
    HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
    int xx;

    if (progTag !=(rpmTag) 0) {
	static const char prog[] = "/bin/sh";	/* XXX FIXME */
	he->tag = progTag;
	he->t = RPM_STRING_TYPE;
	he->p.str = prog;
	he->c = 1;
	xx = headerPut(h, he, 0);
    }

    if (scriptTag != (rpmTag)0 && iob != NULL) {
	he->tag = scriptTag;
	he->t = RPM_STRING_TYPE;
	he->p.str = rpmiobStr(iob);
	he->c = 1;
	xx = headerPut(h, he, 0);
    }
    return 0;
}
Пример #4
0
static void fillOutMainPackage(Header h)
	/*@globals rpmGlobalMacroContext, h_errno, internalState @*/
	/*@modifies h, rpmGlobalMacroContext, internalState @*/
{
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    struct optionalTag *ot;
    int xx;

    for (ot = optionalTags; ot->ot_mac != NULL; ot++) {
	const char * val;
	rpmTag tag;

	tag = ot->ot_tag;

	/* Generate arbitrary tag (if necessary). */
	if (tag == 0xffffffff) {
	    val = tagCanonicalize(ot->ot_mac + (sizeof("%{")-1));
	    tag = tagGenerate(val);
	    val = _free(val);
	}

	if (headerIsEntry(h, tag))
	    continue;
	val = rpmExpand(ot->ot_mac, NULL);
	if (val && *val != '%') {
		he->tag = tag;
		he->t = RPM_STRING_TYPE;
		he->p.str = val;
		he->c = 1;
		xx = headerPut(h, he, 0);
	}
	val = _free(val);
    }
}
Пример #5
0
static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag)
{
    struct rpmtd_s copytd, td;
    rpmtd utd = &td;
    Header nh;
    Header oh;
    HeaderIterator hi;

    if (headerGet(*hdrp, tag, utd, HEADERGET_DEFAULT)) {
	nh = headerNew();
	oh = headerCopyLoad(utd->data);
	hi = headerInitIterator(oh);

	while (headerNext(hi, &copytd)) {
	    if (copytd.data)
		headerPut(nh, &copytd, HEADERPUT_DEFAULT);
	    rpmtdFreeData(&copytd);
	}

	headerFreeIterator(hi);
	headerFree(oh);
	rpmtdFreeData(utd);
	headerFree(*hdrp);
	*hdrp = headerLink(nh);
	headerFree(nh);
    }
}
Пример #6
0
/**
 * This assumes the order of list matches the order of the new headers, and
 * throws an exception if that isn't true.
 */
static int rpmMergeHeaders(PyObject * list, FD_t fd, int matchTag)
{
    Header h;
    HeaderIterator hi;
    rpmTagVal newMatch, oldMatch;
    hdrObject * hdr;
    rpm_count_t count = 0;
    int rc = 1; /* assume failure */
    rpmtd td = rpmtdNew();

    Py_BEGIN_ALLOW_THREADS
    h = headerRead(fd, HEADER_MAGIC_YES);
    Py_END_ALLOW_THREADS

    while (h) {
	if (!headerGet(h, matchTag, td, HEADERGET_MINMEM)) {
	    PyErr_SetString(pyrpmError, "match tag missing in new header");
	    goto exit;
	}
	newMatch = rpmtdTag(td);
	rpmtdFreeData(td);

	hdr = (hdrObject *) PyList_GetItem(list, count++);
	if (!hdr) goto exit;

	if (!headerGet(hdr->h, matchTag, td, HEADERGET_MINMEM)) {
	    PyErr_SetString(pyrpmError, "match tag missing in new header");
	    goto exit;
	}
	oldMatch = rpmtdTag(td);
	rpmtdFreeData(td);

	if (newMatch != oldMatch) {
	    PyErr_SetString(pyrpmError, "match tag mismatch");
	    goto exit;
	}

	for (hi = headerInitIterator(h); headerNext(hi, td); rpmtdFreeData(td))
	{
	    /* could be dupes */
	    headerDel(hdr->h, rpmtdTag(td));
	    headerPut(hdr->h, td, HEADERPUT_DEFAULT);
	}

	headerFreeIterator(hi);
	h = headerFree(h);

	Py_BEGIN_ALLOW_THREADS
	h = headerRead(fd, HEADER_MAGIC_YES);
	Py_END_ALLOW_THREADS
    }
    rc = 0;

exit:
    rpmtdFree(td);
    return rc;
}
Пример #7
0
static void saveOrig(Header h)
{
	struct rpmtd_s td;
	headerGet(h, RPMTAG_BASENAMES, &td, HEADERGET_MINMEM);
	rpmtdSetTag(&td, RPMTAG_ORIGBASENAMES);
	headerPut(h, &td, HEADERPUT_DEFAULT);
	rpmtdFreeData(&td);

	headerGet(h, RPMTAG_DIRNAMES, &td, HEADERGET_MINMEM);
	rpmtdSetTag(&td, RPMTAG_ORIGDIRNAMES);
	headerPut(h, &td, HEADERPUT_DEFAULT);
	rpmtdFreeData(&td);

	headerGet(h, RPMTAG_DIRINDEXES, &td, HEADERGET_MINMEM);
	rpmtdSetTag(&td, RPMTAG_ORIGDIRINDEXES);
	headerPut(h, &td, HEADERPUT_DEFAULT);
	rpmtdFreeData(&td);
}
Пример #8
0
static int addPrefixes(Header h, rpmRelocation *relocations, int numRelocations)
{
    struct rpmtd_s validRelocs;
    const char *validprefix;
    const char ** actualRelocations;
    int numActual = 0;

    headerGet(h, RPMTAG_PREFIXES, &validRelocs, HEADERGET_MINMEM);
    /*
     * If no relocations are specified (usually the case), then return the
     * original header. If there are prefixes, however, then INSTPREFIXES
     * should be added for RPM_INSTALL_PREFIX environ variables in scriptlets, 
     * but, since relocateFileList() can be called more than once for 
     * the same header, don't bother if already present.
     */
    if (relocations == NULL || numRelocations == 0) {
	if (rpmtdCount(&validRelocs) > 0) {
	    if (!headerIsEntry(h, RPMTAG_INSTPREFIXES)) {
		rpmtdSetTag(&validRelocs, RPMTAG_INSTPREFIXES);
		headerPut(h, &validRelocs, HEADERPUT_DEFAULT);
	    }
	    rpmtdFreeData(&validRelocs);
	}
	return 0;
    }

    actualRelocations = xmalloc(rpmtdCount(&validRelocs) * sizeof(*actualRelocations));
    rpmtdInit(&validRelocs);
    while ((validprefix = rpmtdNextString(&validRelocs))) {
	int j;
	for (j = 0; j < numRelocations; j++) {
	    if (relocations[j].oldPath == NULL || /* XXX can't happen */
		!rstreq(validprefix, relocations[j].oldPath))
		continue;
	    /* On install, a relocate to NULL means skip the path. */
	    if (relocations[j].newPath) {
		actualRelocations[numActual] = relocations[j].newPath;
		numActual++;
	    }
	    break;
	}
	if (j == numRelocations) {
	    actualRelocations[numActual] = validprefix;
	    numActual++;
	}
    }
    rpmtdFreeData(&validRelocs);

    if (numActual) {
	headerPutStringArray(h, RPMTAG_INSTPREFIXES, actualRelocations, numActual);
    }
    free(actualRelocations);
    /* When any relocations are present there'll be more work to do */
    return 1;
}
Пример #9
0
/* Dumb wrapper around headerPut() for signature header */
static int sighdrPut(Header h, rpmTagVal tag, rpmTagType type,
                     rpm_data_t p, rpm_count_t c)
{
    struct rpmtd_s sigtd;
    rpmtdReset(&sigtd);
    sigtd.tag = tag;
    sigtd.type = type;
    sigtd.data = p;
    sigtd.count = c;
    return headerPut(h, &sigtd, HEADERPUT_DEFAULT);
}
Пример #10
0
static void saveRelocs(Header h, rpmtd bnames, rpmtd dnames, rpmtd dindexes)
{
	struct rpmtd_s td;
	headerGet(h, RPMTAG_BASENAMES, &td, HEADERGET_MINMEM);
	rpmtdSetTag(&td, RPMTAG_ORIGBASENAMES);
	headerPut(h, &td, HEADERPUT_DEFAULT);
	rpmtdFreeData(&td);

	headerGet(h, RPMTAG_DIRNAMES, &td, HEADERGET_MINMEM);
	rpmtdSetTag(&td, RPMTAG_ORIGDIRNAMES);
	headerPut(h, &td, HEADERPUT_DEFAULT);
	rpmtdFreeData(&td);

	headerGet(h, RPMTAG_DIRINDEXES, &td, HEADERGET_MINMEM);
	rpmtdSetTag(&td, RPMTAG_ORIGDIRINDEXES);
	headerPut(h, &td, HEADERPUT_DEFAULT);
	rpmtdFreeData(&td);

	headerMod(h, bnames);
	headerMod(h, dnames);
	headerMod(h, dindexes);
}
Пример #11
0
static void initSourceHeader(rpmSpec spec)
{
    Package sourcePkg = spec->sourcePackage;
    struct Source *srcPtr;

    if (headerIsEntry(sourcePkg->header, RPMTAG_NAME))
        return;

    /* Only specific tags are added to the source package header */
    headerCopyTags(spec->packages->header, sourcePkg->header, sourceTags);

    /* Add the build restrictions */
    for (int i=0; i<PACKAGE_NUM_DEPS; i++) {
        rpmdsPutToHeader(sourcePkg->dependencies[i], sourcePkg->header);
    }

    {
        HeaderIterator hi = headerInitIterator(spec->buildRestrictions);
        struct rpmtd_s td;
        while (headerNext(hi, &td)) {
            if (rpmtdCount(&td) > 0) {
                (void) headerPut(sourcePkg->header, &td, HEADERPUT_DEFAULT);
            }
            rpmtdFreeData(&td);
        }
        headerFreeIterator(hi);
    }

    if (spec->BANames && spec->BACount > 0) {
        headerPutStringArray(sourcePkg->header, RPMTAG_BUILDARCHS,
                             spec->BANames, spec->BACount);
    }

    /* Add tags for sources and patches */
    for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) {
        if (srcPtr->flags & RPMBUILD_ISSOURCE) {
            headerPutString(sourcePkg->header, RPMTAG_SOURCE, srcPtr->source);
            if (srcPtr->flags & RPMBUILD_ISNO) {
                headerPutUint32(sourcePkg->header, RPMTAG_NOSOURCE,
                                &srcPtr->num, 1);
            }
        }
        if (srcPtr->flags & RPMBUILD_ISPATCH) {
            headerPutString(sourcePkg->header, RPMTAG_PATCH, srcPtr->source);
            if (srcPtr->flags & RPMBUILD_ISNO) {
                headerPutUint32(sourcePkg->header, RPMTAG_NOPATCH,
                                &srcPtr->num, 1);
            }
        }
    }
}
Пример #12
0
/*
 * Validate generated signature and insert to header if it looks sane.
 * NSS doesn't support everything GPG does. Basic tests to see if the 
 * generated signature is something we can use.
 * Return 0 on success, 1 on failure.
 */
static int putSignature(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen)
{
    pgpDigParams sigp = NULL;
    rpmTagVal sigtag;
    struct rpmtd_s sigtd;
    int rc = 1; /* assume failure */
    unsigned int hash_algo;
    unsigned int pubkey_algo;

    if (pgpPrtParams(pkt, pktlen, PGPTAG_SIGNATURE, &sigp)) {
	rpmlog(RPMLOG_ERR, _("Unsupported PGP signature\n"));
	goto exit;
    }

    hash_algo = pgpDigParamsAlgo(sigp, PGPVAL_HASHALGO);
    if (rpmDigestLength(hash_algo) == 0) {
	rpmlog(RPMLOG_ERR, _("Unsupported PGP hash algorithm %u\n"), hash_algo);
	goto exit;
    }

    pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO);
    switch (pubkey_algo) {
    case PGPPUBKEYALGO_DSA:
	sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG;
	break;
    case PGPPUBKEYALGO_RSA:
	sigtag = ishdr ? RPMSIGTAG_RSA : RPMSIGTAG_PGP;
	break;
    default:
	rpmlog(RPMLOG_ERR, _("Unsupported PGP pubkey algorithm %u\n"),
		pubkey_algo);
	goto exit;
	break;
    }

    /* Looks sane, insert into header */
    rpmtdReset(&sigtd);
    sigtd.count = pktlen;
    sigtd.data = pkt;
    sigtd.type = RPM_BIN_TYPE;
    sigtd.tag = sigtag;

    /* Argh, reversed return codes */
    rc = (headerPut(sigh, &sigtd, HEADERPUT_DEFAULT) == 0);

exit:
    pgpDigParamsFree(sigp);
    return rc;
}
Пример #13
0
/** \ingroup header
 * Duplicate a header.
 * @param h		header
 * @return		new header instance
 */
Header headerCopy(Header h)
{
    Header nh = headerNew();
    HeaderIterator hi;
    struct rpmtd_s td;
   
    hi = headerInitIterator(h);
    while (headerNext(hi, &td)) {
	if (rpmtdCount(&td) > 0) {
	    (void) headerPut(nh, &td, HEADERPUT_DEFAULT);
	}
	rpmtdFreeData(&td);
    }
    hi = headerFreeIterator(hi);

    return headerReload(nh, HEADER_IMAGE);
}
Пример #14
0
static void expandFilelist(Header h)
{
    struct rpmtd_s filenames;

    if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
	(void) headerGet(h, RPMTAG_FILENAMES, &filenames, HEADERGET_EXT);
	if (rpmtdCount(&filenames) < 1)
	    return;
	rpmtdSetTag(&filenames, RPMTAG_OLDFILENAMES);
	headerPut(h, &filenames, HEADERPUT_DEFAULT);
	rpmtdFreeData(&filenames);
    }

    (void) headerDel(h, RPMTAG_DIRNAMES);
    (void) headerDel(h, RPMTAG_BASENAMES);
    (void) headerDel(h, RPMTAG_DIRINDEXES);
}
Пример #15
0
Header headerRegenSigHeader(const Header h, int noArchiveSize)
{
    Header sigh = rpmNewSignature();
    HeaderIterator hi;
    struct rpmtd_s td;

    for (hi = headerInitIterator(h); headerNext(hi, &td); rpmtdFreeData(&td)) {
	switch (td.tag) {
	/* XXX Translate legacy signature tag values. */
	case RPMTAG_SIGSIZE:
	    td.tag = RPMSIGTAG_SIZE;
	    break;
	case RPMTAG_SIGPGP:
	    td.tag = RPMSIGTAG_PGP;
	    break;
	case RPMTAG_SIGMD5:
	    td.tag = RPMSIGTAG_MD5;
	    break;
	case RPMTAG_SIGGPG:
	    td.tag = RPMSIGTAG_GPG;
	    break;
	case RPMTAG_SIGPGP5:
	    td.tag = RPMSIGTAG_PGP5;
	    break;
	case RPMTAG_ARCHIVESIZE:
	    /* XXX rpm-4.1 and later has archive size in signature header. */
	    if (noArchiveSize)
		continue;
	    td.tag = RPMSIGTAG_PAYLOADSIZE;
	    break;
	case RPMTAG_SHA1HEADER:
	case RPMTAG_DSAHEADER:
	case RPMTAG_RSAHEADER:
	default:
	    if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
		continue;
	    break;
	}
	if (td.data == NULL) continue;	/* XXX can't happen */
	if (!headerIsEntry(sigh, td.tag))
	    (void) headerPut(sigh, &td, HEADERPUT_DEFAULT);
    }
    hi = headerFreeIterator(hi);
    return sigh;
}
Пример #16
0
void headerCopyTags(Header headerFrom, Header headerTo, 
		    const rpmTag * tagstocopy)
{
    const rpmTag * p;
    struct rpmtd_s td;

    if (headerFrom == headerTo)
	return;

    for (p = tagstocopy; *p != 0; p++) {
	if (headerIsEntry(headerTo, *p))
	    continue;
	if (!headerGet(headerFrom, *p, &td, HEADERGET_MINMEM))
	    continue;
	(void) headerPut(headerTo, &td, HEADERPUT_DEFAULT);
	rpmtdFreeData(&td);
    }
}
Пример #17
0
static void addOrAppendListEntry(Header h, rpmTag tag, char * line)
	/*@modifies h @*/
{
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    int xx;
    int argc;
    const char **argv;

    xx = poptParseArgvString(line, &argc, &argv);
    if (argc) {
	he->tag = tag;
	he->t = RPM_STRING_ARRAY_TYPE;
	he->p.argv = argv;
	he->c = argc;
	he->append = 1;
	xx = headerPut(h, he, 0);
	he->append = 0;
    }
    argv = _free(argv);
}
Пример #18
0
/* make a header with _all_ the tags we need */
static PyObject * hdrFullFilelist(hdrObject * s)
{
    rpmtd fileNames = rpmtdNew();
    Header h = s->h;

    DEPRECATED_METHOD("obsolete method");
    if (!headerIsEntry (h, RPMTAG_BASENAMES)
	|| !headerIsEntry (h, RPMTAG_DIRNAMES)
	|| !headerIsEntry (h, RPMTAG_DIRINDEXES))
	headerConvert(h, HEADERCONV_COMPRESSFILELIST);

    if (headerGet(h, RPMTAG_FILENAMES, fileNames, HEADERGET_EXT)) {
	rpmtdSetTag(fileNames, RPMTAG_OLDFILENAMES);
	headerPut(h, fileNames, HEADERPUT_DEFAULT);
	rpmtdFreeData(fileNames);
    }
    rpmtdFree(fileNames);

    Py_RETURN_NONE;
}
Пример #19
0
int headerModifyEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
			rpm_constdata_t p, rpm_count_t c)
{
    struct rpmtd_s td = {
	.tag = tag,
	.type = type,
	.data = (void *) p,
	.count = c,
    };
    return headerMod(h, &td);
}

static int headerPutWrap(Header h, rpm_tag_t tag, rpm_tagtype_t type,
		rpm_constdata_t p, rpm_count_t c, headerPutFlags flags)
{
    struct rpmtd_s td = {
	.tag = tag,
	.type = type,
	.data = (void *) p,
	.count = c,
    };
    return headerPut(h, &td, flags);
}

int headerAddOrAppendEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
		rpm_constdata_t p, rpm_count_t c)
{
    return headerPutWrap(h, tag, type, p, c, HEADERPUT_APPEND);
}

int headerAppendEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
		rpm_constdata_t p, rpm_count_t c)
{
    return headerPutWrap(h, tag, type, p, c, HEADERPUT_APPEND);
}

int headerAddEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
		rpm_constdata_t p, rpm_count_t c)
{
    return headerPutWrap(h, tag, type, p, c, HEADERPUT_DEFAULT);
}
Пример #20
0
/*
 * Sanity check data types against tag table before putting. Assume
 * append on all array-types.
 */
static int headerPutType(Header h, rpmTagVal tag, rpmTagType reqtype,
			rpm_constdata_t data, rpm_count_t size)
{
    struct rpmtd_s td;
    rpmTagType type = rpmTagGetTagType(tag);
    rpmTagReturnType retype = rpmTagGetReturnType(tag);
    headerPutFlags flags = HEADERPUT_APPEND; 
    int valid = 1;

    /* Basic sanity checks: type must match and there must be data to put */
    if (type != reqtype 
	|| size < 1 || data == NULL || h == NULL) {
	valid = 0;
    }

    /*
     * Non-array types can't be appended to. Binary types use size
     * for data length, for other non-array types size must be 1.
     */
    if (retype != RPM_ARRAY_RETURN_TYPE) {
	flags = HEADERPUT_DEFAULT;
	if (type != RPM_BIN_TYPE && size != 1) {
	    valid = 0;
	}
    }

    if (valid) {
	rpmtdReset(&td);
	td.tag = tag;
	td.type = type;
	td.data = (void *) data;
	td.count = size;

	valid = headerPut(h, &td, flags);
    }

    return valid;
}
Пример #21
0
rpmRC rpmGenerateSignature(char *SHA1, uint8_t *MD5, rpm_loff_t size,
				rpm_loff_t payloadSize, FD_t fd)
{
    Header sig = headerNew();
    struct rpmtd_s td;
    rpmRC rc = RPMRC_OK;
    char *reservedSpace;
    int spaceSize = 32; /* always reserve a bit of space */
    int gpgSize = rpmExpandNumeric("%{__gpg_reserved_space}");

    /* Prepare signature */
    rpmtdReset(&td);
    td.tag = RPMSIGTAG_SHA1;
    td.count = 1;
    td.type = RPM_STRING_TYPE;
    td.data = SHA1;
    headerPut(sig, &td, HEADERPUT_DEFAULT);

    rpmtdReset(&td);
    td.tag = RPMSIGTAG_MD5;
    td.count = 16;
    td.type = RPM_BIN_TYPE;
    td.data = MD5;
    headerPut(sig, &td, HEADERPUT_DEFAULT);

    rpmtdReset(&td);
    td.count = 1;
    if (payloadSize < UINT32_MAX) {
	rpm_off_t p = payloadSize;
	rpm_off_t s = size;
	td.type = RPM_INT32_TYPE;

	td.tag = RPMSIGTAG_PAYLOADSIZE;
	td.data = &p;
	headerPut(sig, &td, HEADERPUT_DEFAULT);

	td.tag = RPMSIGTAG_SIZE;
	td.data = &s;
	headerPut(sig, &td, HEADERPUT_DEFAULT);
    } else {
	rpm_loff_t p = payloadSize;
	rpm_loff_t s = size;
	td.type = RPM_INT64_TYPE;

	td.tag = RPMSIGTAG_LONGARCHIVESIZE;
	td.data = &p;
	headerPut(sig, &td, HEADERPUT_DEFAULT);

	td.tag = RPMSIGTAG_LONGSIZE;
	td.data = &s;
	headerPut(sig, &td, HEADERPUT_DEFAULT);

	/* adjust for the size difference between 64- and 32bit tags */
	spaceSize -= 8;
    }

    if (gpgSize > 0)
	spaceSize += gpgSize;

    if(spaceSize > 0) {
	reservedSpace = xcalloc(spaceSize, sizeof(char));
	rpmtdReset(&td);
	td.tag = RPMSIGTAG_RESERVEDSPACE;
	td.count = spaceSize;
	td.type = RPM_BIN_TYPE;
	td.data = reservedSpace;
	headerPut(sig, &td, HEADERPUT_DEFAULT);
	free(reservedSpace);
    }

    /* Reallocate the signature into one contiguous region. */
    sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
    if (sig == NULL) { /* XXX can't happen */
	rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
	rc = RPMRC_FAIL;
	goto exit;
    }

    /* Write the signature section into the package. */
    if (rpmWriteSignature(fd, sig)) {
	rc = RPMRC_FAIL;
	goto exit;
    }

exit:
    headerFree(sig);
    return rc;
}
Пример #22
0
static int doIcon(Spec spec, Header h)
	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
	/*@modifies h, rpmGlobalMacroContext, fileSystem, internalState  @*/
{
    static size_t iconsize = 0;
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    const char *fn, *Lurlfn = NULL;
    struct Source *sp;
    size_t nb;
    rpmuint8_t * icon;
    FD_t fd = NULL;
    int rc = RPMRC_FAIL;	/* assume error */
    int urltype;
    int xx;

    if (iconsize == 0) {
	iconsize = rpmExpandNumeric("%{?_build_iconsize}");
	if (iconsize < 2048)
	    iconsize = 2048;
    }
    icon = alloca(iconsize+1);

    for (sp = spec->sources; sp != NULL; sp = sp->next) {
	if (sp->flags & RPMFILE_ICON)
	    break;
    }
    if (sp == NULL) {
	rpmlog(RPMLOG_ERR, _("No icon file in sources\n"));
	goto exit;
    }

#if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    /* support splitted source directories, i.e., source files which
       are alternatively placed into the .spec directory and picked
       up from there, too. */
    Lurlfn = rpmGenPath(NULL, "%{_specdir}/", sp->source);
    if (access(Lurlfn, F_OK) == -1) {
        Lurlfn = _free(Lurlfn);
        Lurlfn = rpmGenPath(NULL, "%{_icondir}/", sp->source);
    }
#else
    Lurlfn = rpmGenPath(NULL, "%{_icondir}/", sp->source);
#endif

    fn = NULL;
    urltype = urlPath(Lurlfn, &fn);
    switch (urltype) {  
    case URL_IS_HTTPS: 
    case URL_IS_HTTP:
    case URL_IS_FTP:
    case URL_IS_PATH:
    case URL_IS_UNKNOWN:
	break;
    case URL_IS_DASH:
    case URL_IS_HKP:
    case URL_IS_MONGO:	/* XXX FIXME */
	rpmlog(RPMLOG_ERR, _("Invalid icon URL: %s\n"), Lurlfn);
	goto exit;
	/*@notreached@*/ break;
    }

    fd = Fopen(fn, "r%{?_rpmgio}");
    if (fd == NULL || Ferror(fd)) {
	rpmlog(RPMLOG_ERR, _("Unable to open icon %s: %s\n"),
		fn, Fstrerror(fd));
	rc = RPMRC_FAIL;
	goto exit;
    }

    *icon = '\0';
    nb = Fread(icon, sizeof(icon[0]), iconsize, fd);
    if (Ferror(fd) || nb == 0) {
	rpmlog(RPMLOG_ERR, _("Unable to read icon %s: %s\n"),
		fn, Fstrerror(fd));
	goto exit;
    }
    if (nb >= iconsize) {
	rpmlog(RPMLOG_ERR, _("Icon %s is too big (max. %d bytes)\n"),
		fn, (int)iconsize);
	goto exit;
    }

    if (icon[0] == 'G' && icon[1] == 'I' && icon[2] == 'F')
	he->tag = RPMTAG_GIF;
    else
    if (icon[0] == '/' && icon[1] == '*' && icon[2] == ' '
     && icon[3] == 'X' && icon[4] == 'P' && icon[5] == 'M')
	he->tag = RPMTAG_XPM;
    else
	he->tag = tagValue("Icon");
    he->t = RPM_BIN_TYPE;
    he->p.ui8p = icon;
    he->c = (rpmTagCount)nb;
    xx = headerPut(h, he, 0);
    rc = 0;
    
exit:
    if (fd) {
	(void) Fclose(fd);
	fd = NULL;
    }
    Lurlfn = _free(Lurlfn);
    return rc;
}
Пример #23
0
static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag,
		const char *macro, const char *lang)
	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
	/*@modifies spec->macros, spec->st,
		spec->sources, spec->numSources, spec->noSource,
		spec->sourceHeader, spec->BANames, spec->BACount,
		spec->line,
		pkg->header, pkg->autoProv, pkg->autoReq, pkg->noarch,
		rpmGlobalMacroContext, fileSystem, internalState @*/
{
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    char * field = spec->line;
    char * end;
    int multiToken = 0;
    rpmsenseFlags tagflags;
    int len;
    rpmuint32_t num;
    int rc;
    int xx;
    
    if (field == NULL) return RPMRC_FAIL;	/* XXX can't happen */
    /* Find the start of the "field" and strip trailing space */
    while ((*field) && (*field != ':'))
	field++;
    if (*field != ':') {
	rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"),
		 spec->lineNum, spec->line);
	return RPMRC_FAIL;
    }
    field++;
    SKIPSPACE(field);
    if (!*field) {
	/* Empty field */
	rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"),
		 spec->lineNum, spec->line);
	return RPMRC_FAIL;
    }
    end = findLastChar(field);

    /* Validate tag data content. */
    if (tagValidate(spec, tag, field) != RPMRC_OK)
	return RPMRC_FAIL;

    /* See if this is multi-token */
    end = field;
    SKIPNONSPACE(end);
    if (*end != '\0')
	multiToken = 1;

    switch (tag) {
    case RPMTAG_NAME:
    case RPMTAG_VERSION:
    case RPMTAG_RELEASE:
    case RPMTAG_DISTEPOCH:
    case RPMTAG_URL:
    case RPMTAG_DISTTAG:
    case RPMTAG_REPOTAG:
    case RPMTAG_CVSID:
    case RPMTAG_BUGURL:
	SINGLE_TOKEN_ONLY;
	/* These macros are for backward compatibility */
	if (tag == RPMTAG_VERSION) {
	    if (strchr(field, '-') != NULL) {
		rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
		    spec->lineNum, "version", spec->line);
		return RPMRC_FAIL;
	    }
	    addMacro(spec->macros, "PACKAGE_VERSION", NULL, field, RMIL_OLDSPEC);
	} else if (tag == RPMTAG_RELEASE) {
	    if (strchr(field, '-') != NULL) {
		rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
		    spec->lineNum, "release", spec->line);
		return RPMRC_FAIL;
	    }
	    addMacro(spec->macros, "PACKAGE_RELEASE", NULL, field, RMIL_OLDSPEC-1);
	}
	he->tag = tag;
	he->t = RPM_STRING_TYPE;
	he->p.str = field;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);
	break;
    case RPMTAG_GROUP:
    case RPMTAG_SUMMARY:
#if defined(RPM_VENDOR_OPENPKG) /* make-class-available-as-macro */
    case RPMTAG_CLASS:
#endif
	(void) stashSt(spec, pkg->header, tag, lang);
	/*@fallthrough@*/
    case RPMTAG_DISTRIBUTION:
    case RPMTAG_VENDOR:
    case RPMTAG_LICENSE:
    case RPMTAG_PACKAGER:
	if (!*lang) {
	    he->tag = tag;
	    he->t = RPM_STRING_TYPE;
	    he->p.str = field;
	    he->c = 1;
	    xx = headerPut(pkg->header, he, 0);
	} else if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG))) {
	    (void) headerAddI18NString(pkg->header, tag, field, lang);
	}
	break;
    /* XXX silently ignore BuildRoot: */
    case RPMTAG_BUILDROOT:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
#ifdef	DYING
	buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
	(void) urlPath(buildRootURL, &buildRoot);
	if (*buildRoot == '\0') buildRoot = "/";
	if (!strcmp(buildRoot, "/")) {
	    rpmlog(RPMLOG_ERR,
		     _("BuildRoot can not be \"/\": %s\n"), spec->buildRootURL);
	    buildRootURL = _free(buildRootURL);
	    return RPMRC_FAIL;
	}
	buildRootURL = _free(buildRootURL);
#endif
	break;
    case RPMTAG_KEYWORDS:
    case RPMTAG_VARIANTS:
    case RPMTAG_PREFIXES:
	addOrAppendListEntry(pkg->header, tag, field);
	he->tag = tag;
	xx = headerGet(pkg->header, he, 0);
	if (tag == RPMTAG_PREFIXES)
	while (he->c--) {
	    if (he->p.argv[he->c][0] != '/') {
		rpmlog(RPMLOG_ERR,
			 _("line %d: Prefixes must begin with \"/\": %s\n"),
			 spec->lineNum, spec->line);
		he->p.ptr = _free(he->p.ptr);
		return RPMRC_FAIL;
	    }
	    len = (int)strlen(he->p.argv[he->c]);
	    if (he->p.argv[he->c][len - 1] == '/' && len > 1) {
		rpmlog(RPMLOG_ERR,
			 _("line %d: Prefixes must not end with \"/\": %s\n"),
			 spec->lineNum, spec->line);
		he->p.ptr = _free(he->p.ptr);
		return RPMRC_FAIL;
	    }
	}
	he->p.ptr = _free(he->p.ptr);
	break;
    case RPMTAG_DOCDIR:
	SINGLE_TOKEN_ONLY;
	if (field[0] != '/') {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Docdir must begin with '/': %s\n"),
		     spec->lineNum, spec->line);
	    return RPMRC_FAIL;
	}
	macro = NULL;
	delMacro(NULL, "_docdir");
	addMacro(NULL, "_docdir", NULL, field, RMIL_SPEC);
	break;
    case RPMTAG_XMAJOR:
    case RPMTAG_XMINOR:
    case RPMTAG_EPOCH:
	SINGLE_TOKEN_ONLY;
	if (parseNum(field, &num)) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: %s takes an integer value: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return RPMRC_FAIL;
	}
	he->tag = tag;
	he->t = RPM_UINT32_TYPE;
	he->p.ui32p = &num;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);
	break;
    case RPMTAG_AUTOREQPROV:
	pkg->autoReq = parseYesNo(field);
	pkg->autoProv = pkg->autoReq;
	break;
    case RPMTAG_AUTOREQ:
	pkg->autoReq = parseYesNo(field);
	break;
    case RPMTAG_AUTOPROV:
	pkg->autoProv = parseYesNo(field);
	break;
    case RPMTAG_SOURCE:
    case RPMTAG_PATCH:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
	if ((rc = addSource(spec, pkg, field, tag)))
	    return rc;
	break;
    case RPMTAG_ICON:
	SINGLE_TOKEN_ONLY;
	macro = NULL;
	if ((rc = addSource(spec, pkg, field, tag)))
	    return rc;
	/* XXX the fetch/load of icon needs to be elsewhere. */
	if ((rc = doIcon(spec, pkg->header)))
	    return rc;
	break;
    case RPMTAG_NOSOURCE:
    case RPMTAG_NOPATCH:
	spec->noSource = 1;
	if ((rc = parseNoSource(spec, field, tag)))
	    return rc;
	break;
    case RPMTAG_BUILDPREREQ:
    case RPMTAG_BUILDREQUIRES:
	if ((rc = parseBits(lang, buildScriptBits, &tagflags))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad %s: qualifiers: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return rc;
	}
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_PREREQ:
    case RPMTAG_REQUIREFLAGS:
	if ((rc = parseBits(lang, installScriptBits, &tagflags))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad %s: qualifiers: %s\n"),
		     spec->lineNum, tagName(tag), spec->line);
	    return rc;
	}
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    /* Aliases for BuildRequires(hint): */
    case RPMTAG_BUILDSUGGESTS:
    case RPMTAG_BUILDENHANCES:
	tagflags = RPMSENSE_MISSINGOK;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    /* Aliases for Requires(hint): */
    case RPMTAG_SUGGESTSFLAGS:
    case RPMTAG_ENHANCESFLAGS:
	tag = RPMTAG_REQUIREFLAGS;
	tagflags = RPMSENSE_MISSINGOK;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_BUILDOBSOLETES:
    case RPMTAG_BUILDPROVIDES:
    case RPMTAG_BUILDCONFLICTS:
    case RPMTAG_CONFLICTFLAGS:
    case RPMTAG_OBSOLETEFLAGS:
    case RPMTAG_PROVIDEFLAGS:
	tagflags = RPMSENSE_ANY;
	if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
	    return rc;
	break;
    case RPMTAG_BUILDPLATFORMS:		/* XXX needs pattern parsing */
    case RPMTAG_EXCLUDEARCH:
    case RPMTAG_EXCLUSIVEARCH:
    case RPMTAG_EXCLUDEOS:
    case RPMTAG_EXCLUSIVEOS:
	addOrAppendListEntry(spec->sourceHeader, tag, field);
	break;

    case RPMTAG_BUILDARCHS:
    {	const char ** BANames = NULL;
	int BACount = 0;
	if ((rc = poptParseArgvString(field, &BACount, &BANames))) {
	    rpmlog(RPMLOG_ERR,
		     _("line %d: Bad BuildArchitecture format: %s\n"),
		     spec->lineNum, spec->line);
	    return RPMRC_FAIL;
	}
	if (spec->toplevel) {
	    if (BACount > 0 && BANames != NULL) {
		spec->BACount = BACount;
		spec->BANames = BANames;
		BANames = NULL;		/* XXX don't free. */
	    }
	} else {
	    if (BACount != 1 || strcmp(BANames[0], "noarch")) {
		rpmlog(RPMLOG_ERR,
		     _("line %d: Only \"noarch\" sub-packages are supported: %s\n"),
		     spec->lineNum, spec->line);
		BANames = _free(BANames);
		return RPMRC_FAIL;
	    }
	    pkg->noarch = 1;
	}
	BANames = _free(BANames);
    }	break;

    default:
	macro = NULL;
	he->tag = tag;
	he->t = RPM_STRING_ARRAY_TYPE;
	he->p.argv= (const char **) &field;	/* XXX NOCAST */
	he->c = 1;
	he->append = 1;
	xx = headerPut(pkg->header, he, 0);
	he->append = 0;
	break;
    }

/*@-usereleased@*/
    if (macro)
	addMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
/*@=usereleased@*/
    
    return RPMRC_OK;
}
Пример #24
0
/** \ingroup header
 * Translate and merge legacy signature tags into header.
 * @param h		header (dest)
 * @param sigh		signature header (src)
 */
static void headerMergeLegacySigs(Header h, Header sigh)
{
    HeaderIterator hi;
    struct rpmtd_s td;

    hi = headerInitIterator(sigh);
    for (; headerNext(hi, &td); rpmtdFreeData(&td))
    {
	switch (td.tag) {
	/* XXX Translate legacy signature tag values. */
	case RPMSIGTAG_SIZE:
	    td.tag = RPMTAG_SIGSIZE;
	    break;
	case RPMSIGTAG_PGP:
	    td.tag = RPMTAG_SIGPGP;
	    break;
	case RPMSIGTAG_MD5:
	    td.tag = RPMTAG_SIGMD5;
	    break;
	case RPMSIGTAG_GPG:
	    td.tag = RPMTAG_SIGGPG;
	    break;
	case RPMSIGTAG_PGP5:
	    td.tag = RPMTAG_SIGPGP5;
	    break;
	case RPMSIGTAG_PAYLOADSIZE:
	    td.tag = RPMTAG_ARCHIVESIZE;
	    break;
	case RPMSIGTAG_SHA1:
	case RPMSIGTAG_DSA:
	case RPMSIGTAG_RSA:
	default:
	    if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
		continue;
	    break;
	}
	if (!headerIsEntry(h, td.tag)) {
	    switch(td.type) {
	    case RPM_NULL_TYPE:
		continue;
		break;
	    case RPM_CHAR_TYPE:
	    case RPM_INT8_TYPE:
	    case RPM_INT16_TYPE:
	    case RPM_INT32_TYPE:
	    case RPM_INT64_TYPE:
		if (td.count != 1)
		    continue;
		break;
	    case RPM_STRING_TYPE:
	    case RPM_BIN_TYPE:
		if (td.count >= 16*1024)
		    continue;
		break;
	    case RPM_STRING_ARRAY_TYPE:
	    case RPM_I18NSTRING_TYPE:
		continue;
		break;
	    }
	    (void) headerPut(h, &td, HEADERPUT_DEFAULT);
	}
    }
    headerFreeIterator(hi);
}
Пример #25
0
int headerAddI18NString(Header h, rpmTagVal tag, const char * string,
		const char * lang)
{
    indexEntry table, entry;
    const char ** strArray;
    int length;
    int ghosts;
    rpm_count_t i, langNum;
    char * buf;

    table = findEntry(h, RPMTAG_HEADERI18NTABLE, RPM_STRING_ARRAY_TYPE);
    entry = findEntry(h, tag, RPM_I18NSTRING_TYPE);

    if (!table && entry)
	return 0;		/* this shouldn't ever happen!! */

    if (!table && !entry) {
	const char * charArray[2];
	rpm_count_t count = 0;
	struct rpmtd_s td;
	if (!lang || (lang[0] == 'C' && lang[1] == '\0')) {
	    charArray[count++] = "C";
	} else {
	    charArray[count++] = "C";
	    charArray[count++] = lang;
	}
	
	rpmtdReset(&td);
	td.tag = RPMTAG_HEADERI18NTABLE;
	td.type = RPM_STRING_ARRAY_TYPE;
	td.data = (void *) charArray;
	td.count = count;
	if (!headerPut(h, &td, HEADERPUT_DEFAULT))
	    return 0;
	table = findEntry(h, RPMTAG_HEADERI18NTABLE, RPM_STRING_ARRAY_TYPE);
    }

    if (!table)
	return 0;
    if (!lang) lang = "C";

    {	const char * l = table->data;
	for (langNum = 0; langNum < table->info.count; langNum++) {
	    if (rstreq(l, lang)) break;
	    l += strlen(l) + 1;
	}
    }

    if (langNum >= table->info.count) {
	length = strlen(lang) + 1;
	if (ENTRY_IN_REGION(table)) {
	    char * t = xmalloc(table->length + length);
	    memcpy(t, table->data, table->length);
	    table->data = t;
	    table->info.offset = 0;
	} else
	    table->data = xrealloc(table->data, table->length + length);
	memmove(((char *)table->data) + table->length, lang, length);
	table->length += length;
	table->info.count++;
    }

    if (!entry) {
	int rc;
	struct rpmtd_s td;
	strArray = xmalloc(sizeof(*strArray) * (langNum + 1));
	for (i = 0; i < langNum; i++)
	    strArray[i] = "";
	strArray[langNum] = string;

	rpmtdReset(&td);
	td.tag = tag;
	td.type = RPM_I18NSTRING_TYPE;
	td.data = strArray;
	td.count = langNum + 1;
	rc = headerPut(h, &td, HEADERPUT_DEFAULT);
	free(strArray);
	return rc;
    } else if (langNum >= entry->info.count) {
	ghosts = langNum - entry->info.count;
	
	length = strlen(string) + 1 + ghosts;
	if (ENTRY_IN_REGION(entry)) {
	    char * t = xmalloc(entry->length + length);
	    memcpy(t, entry->data, entry->length);
	    entry->data = t;
	    entry->info.offset = 0;
	} else
	    entry->data = xrealloc(entry->data, entry->length + length);

	memset(((char *)entry->data) + entry->length, '\0', ghosts);
	memmove(((char *)entry->data) + entry->length + ghosts, string, strlen(string)+1);

	entry->length += length;
	entry->info.count = langNum + 1;
    } else {
	char *b, *be, *e, *ee, *t;
	size_t bn, sn, en;

	/* Set beginning/end pointers to previous data */
	b = be = e = ee = entry->data;
	for (i = 0; i < table->info.count; i++) {
	    if (i == langNum)
		be = ee;
	    ee += strlen(ee) + 1;
	    if (i == langNum)
		e  = ee;
	}

	/* Get storage for new buffer */
	bn = (be-b);
	sn = strlen(string) + 1;
	en = (ee-e);
	length = bn + sn + en;
	t = buf = xmalloc(length);

	/* Copy values into new storage */
	memcpy(t, b, bn);
	t += bn;
	memcpy(t, string, sn);
	t += sn;
	memcpy(t, e, en);
	t += en;

	/* Replace i18N string array */
	entry->length -= strlen(be) + 1;
	entry->length += sn;
	
	if (ENTRY_IN_REGION(entry)) {
	    entry->info.offset = 0;
	} else
	    entry->data = _free(entry->data);
	entry->data = buf;
    }

    return 0;
}
Пример #26
0
Файл: pack.c Проект: kaltsi/rpm
static rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName,
	     CSA_t csa, char **cookie)
{
    FD_t fd = NULL;
    FD_t ifd = NULL;
    ssize_t count;
    char * sigtarget = NULL;;
    char * rpmio_flags = NULL;
    char * SHA1 = NULL;
    const char *s;
    char *buf = NULL;
    Header h;
    Header sig = NULL;
    int xx;
    rpmRC rc = RPMRC_OK;
    struct rpmtd_s td;
    rpmTagVal sizetag;
    rpmTagVal payloadtag;

    /* Transfer header reference form *hdrp to h. */
    h = headerLink(*hdrp);
    *hdrp = headerFree(*hdrp);

    if (pkgidp)
	*pkgidp = NULL;

    /* Save payload information */
    if (headerIsSource(h))
	rpmio_flags = rpmExpand("%{?_source_payload}", NULL);
    else 
	rpmio_flags = rpmExpand("%{?_binary_payload}", NULL);

    if (!(rpmio_flags && *rpmio_flags)) {
	rpmio_flags = _free(rpmio_flags);
	rpmio_flags = xstrdup("w9.gzdio");
    }
    s = strchr(rpmio_flags, '.');
    if (s) {
	const char *compr = NULL;
	headerPutString(h, RPMTAG_PAYLOADFORMAT, "cpio");

	if (rstreq(s+1, "ufdio")) {
	    compr = NULL;
	} else if (rstreq(s+1, "gzdio")) {
	    compr = "gzip";
#if HAVE_BZLIB_H
	} else if (rstreq(s+1, "bzdio")) {
	    compr = "bzip2";
	    /* Add prereq on rpm version that understands bzip2 payloads */
	    (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1");
#endif
#if HAVE_LZMA_H
	} else if (rstreq(s+1, "xzdio")) {
	    compr = "xz";
	    (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1");
	} else if (rstreq(s+1, "lzdio")) {
	    compr = "lzma";
	    (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1");
#endif
	} else {
	    rpmlog(RPMLOG_ERR, _("Unknown payload compression: %s\n"),
		   rpmio_flags);
	    rc = RPMRC_FAIL;
	    goto exit;
	}

	if (compr)
	    headerPutString(h, RPMTAG_PAYLOADCOMPRESSOR, compr);
	buf = xstrdup(rpmio_flags);
	buf[s - rpmio_flags] = '\0';
	headerPutString(h, RPMTAG_PAYLOADFLAGS, buf+1);
	free(buf);
    }

    /* Create and add the cookie */
    if (cookie) {
	rasprintf(cookie, "%s %d", buildHost(), (int) (*getBuildTime()));
	headerPutString(h, RPMTAG_COOKIE, *cookie);
    }
    
    /* Reallocate the header into one contiguous region. */
    h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
    if (h == NULL) {	/* XXX can't happen */
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to create immutable header region.\n"));
	goto exit;
    }
    /* Re-reference reallocated header. */
    *hdrp = headerLink(h);

    /*
     * Write the header+archive into a temp file so that the size of
     * archive (after compression) can be added to the header.
     */
    fd = rpmMkTempFile(NULL, &sigtarget);
    if (fd == NULL || Ferror(fd)) {
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
	goto exit;
    }

    fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
    if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to write temp header\n"));
    } else { /* Write the archive and get the size */
	(void) Fflush(fd);
	fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1);
	if (csa->cpioList != NULL) {
	    rc = cpio_doio(fd, h, csa, rpmio_flags);
	} else if (Fileno(csa->cpioFdIn) >= 0) {
	    rc = cpio_copy(fd, csa);
	} else {
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Bad CSA data\n"));
	}
    }

    if (rc != RPMRC_OK)
	goto exit;

    (void) Fclose(fd);
    fd = NULL;
    (void) unlink(fileName);

    /* Generate the signature */
    (void) fflush(stdout);
    sig = rpmNewSignature();

    /*
     * There should be rpmlib() dependency on this, but that doesn't
     * really do much good as these are signature tags that get read
     * way before dependency checking has a chance to figure out anything.
     * On the positive side, not inserting the 32bit tag at all means
     * older rpm will just bail out with error message on attempt to read
     * such a package.
     */
    if (csa->cpioArchiveSize < UINT32_MAX) {
	sizetag = RPMSIGTAG_SIZE;
	payloadtag = RPMSIGTAG_PAYLOADSIZE;
    } else {
	sizetag = RPMSIGTAG_LONGSIZE;
	payloadtag = RPMSIGTAG_LONGARCHIVESIZE;
    }
    (void) rpmGenDigest(sig, sigtarget, sizetag);
    (void) rpmGenDigest(sig, sigtarget, RPMSIGTAG_MD5);

    if (SHA1) {
	/* XXX can't use rpmtdFromFoo() on RPMSIGTAG_* items */
	rpmtdReset(&td);
	td.tag = RPMSIGTAG_SHA1;
	td.type = RPM_STRING_TYPE;
	td.data = SHA1;
	td.count = 1;
	headerPut(sig, &td, HEADERPUT_DEFAULT);
	SHA1 = _free(SHA1);
    }

    {	
	/* XXX can't use headerPutType() on legacy RPMSIGTAG_* items */
	rpmtdReset(&td);
	td.tag = payloadtag;
	td.count = 1;
	if (payloadtag == RPMSIGTAG_PAYLOADSIZE) {
	    rpm_off_t asize = csa->cpioArchiveSize;
	    td.type = RPM_INT32_TYPE;
	    td.data = &asize;
	    headerPut(sig, &td, HEADERPUT_DEFAULT);
	} else {
	    rpm_loff_t asize = csa->cpioArchiveSize;
	    td.type = RPM_INT64_TYPE;
	    td.data = &asize;
	    headerPut(sig, &td, HEADERPUT_DEFAULT);
	}
    }

    /* Reallocate the signature into one contiguous region. */
    sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
    if (sig == NULL) {	/* XXX can't happen */
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
	goto exit;
    }

    /* Open the output file */
    fd = Fopen(fileName, "w.ufdio");
    if (fd == NULL || Ferror(fd)) {
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"),
		fileName, Fstrerror(fd));
	goto exit;
    }

    /* Write the lead section into the package. */
    {	
	rpmlead lead = rpmLeadFromHeader(h);
	rc = rpmLeadWrite(fd, lead);
	lead = rpmLeadFree(lead);
	if (rc != RPMRC_OK) {
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
		 Fstrerror(fd));
	    goto exit;
	}
    }

    /* Write the signature section into the package. */
    if (rpmWriteSignature(fd, sig)) {
	rc = RPMRC_FAIL;
	goto exit;
    }

    /* Append the header and archive */
    ifd = Fopen(sigtarget, "r.ufdio");
    if (ifd == NULL || Ferror(ifd)) {
	rc = RPMRC_FAIL;
	rpmlog(RPMLOG_ERR, _("Unable to open sigtarget %s: %s\n"),
		sigtarget, Fstrerror(ifd));
	goto exit;
    }

    /* Add signatures to header, and write header into the package. */
    /* XXX header+payload digests/signatures might be checked again here. */
    {	Header nh = headerRead(ifd, HEADER_MAGIC_YES);

	if (nh == NULL) {
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to read header from %s: %s\n"),
			sigtarget, Fstrerror(ifd));
	    goto exit;
	}

#ifdef	NOTYET
	(void) headerMergeLegacySigs(nh, sig);
#endif

	xx = headerWrite(fd, nh, HEADER_MAGIC_YES);
	nh = headerFree(nh);

	if (xx) {
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to write header to %s: %s\n"),
			fileName, Fstrerror(fd));
	    goto exit;
	}
    }
	
    /* Write the payload into the package. */
    buf = xmalloc(BUFSIZ);
    while ((count = Fread(buf, 1, BUFSIZ, ifd)) > 0) {
	if (count == -1) {
	    free(buf);
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to read payload from %s: %s\n"),
		     sigtarget, Fstrerror(ifd));
	    goto exit;
	}
	if (Fwrite(buf, sizeof(buf[0]), count, fd) != count) {
	    free(buf);
	    rc = RPMRC_FAIL;
	    rpmlog(RPMLOG_ERR, _("Unable to write payload to %s: %s\n"),
		     fileName, Fstrerror(fd));
	    goto exit;
	}
    }
    free(buf);
    rc = RPMRC_OK;

exit:
    rpmio_flags = _free(rpmio_flags);
    SHA1 = _free(SHA1);
    h = headerFree(h);

    /* XXX Fish the pkgid out of the signature header. */
    if (sig != NULL && pkgidp != NULL) {
	struct rpmtd_s md5tag;
	headerGet(sig, RPMSIGTAG_MD5, &md5tag, HEADERGET_DEFAULT);
	if (rpmtdType(&md5tag) == RPM_BIN_TYPE &&
	    			md5tag.count == 16 && md5tag.data != NULL) {
	    *pkgidp = md5tag.data;
	}
    }

    sig = rpmFreeSignature(sig);
    if (ifd) {
	(void) Fclose(ifd);
	ifd = NULL;
    }
    if (fd) {
	(void) Fclose(fd);
	fd = NULL;
    }
    if (sigtarget) {
	(void) unlink(sigtarget);
	sigtarget = _free(sigtarget);
    }

    if (rc == RPMRC_OK)
	rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fileName);
    else
	(void) unlink(fileName);

    return rc;
}
Пример #27
0
/* XXX should return rpmParseState, but RPMRC_FAIL forces int return. */
int parsePreamble(Spec spec, int initialPackage)
{
    HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    rpmParseState nextPart;
    int xx;
    char *linep;
    Package pkg;
    char NVR[BUFSIZ];
    char lang[BUFSIZ];
    rpmRC rc;

    strcpy(NVR, "(main package)");

    pkg = newPackage(spec);
    if (spec->packages == NULL) {
	spec->packages = pkg;
assert(initialPackage);
    } else if (! initialPackage) {
	char *name = NULL;
	rpmParseState flag;
	Package lastpkg;

	/* There is one option to %package: <pkg> or -n <pkg> */
	flag = PART_NONE;
	if (parseSimplePart(spec, &name, &flag)) {
	    rpmlog(RPMLOG_ERR, _("Bad package specification: %s\n"),
			spec->line);
	    pkg = freePackages(pkg);
	    return RPMRC_FAIL;
	}
	
	lastpkg = NULL;
	if (lookupPackage(spec, name, flag, &lastpkg) == RPMRC_OK) {
	    pkg->next = lastpkg->next;
	} else {
	    /* Add package to end of list */
	    for (lastpkg = spec->packages; lastpkg->next != NULL; lastpkg = lastpkg->next)
	    {};
	}
assert(lastpkg != NULL);
	lastpkg->next = pkg;
	
	/* Construct the package */
	if (flag == PART_SUBNAME) {
	    he->tag = RPMTAG_NAME;
	    xx = headerGet(spec->packages->header, he, 0);
	    sprintf(NVR, "%s-%s", he->p.str, name);
	    he->p.ptr = _free(he->p.ptr);
	} else
	    strcpy(NVR, name);
	name = _free(name);
	he->tag = RPMTAG_NAME;
	he->t = RPM_STRING_TYPE;
	he->p.str = NVR;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);
    }

    if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
	nextPart = PART_NONE;
    } else {
	if (rc)
	    return rc;
	while ((nextPart = isPart(spec)) == PART_NONE) {
	    const char * macro = NULL;
	    rpmTag tag = 0;

	    /* Skip blank lines */
	    linep = spec->line;
	    SKIPSPACE(linep);
	    if (*linep != '\0') {
		if (findPreambleTag(spec, &tag, &macro, lang)) {
		    rpmlog(RPMLOG_ERR, _("line %d: Unknown tag: %s\n"),
				spec->lineNum, spec->line);
		    return RPMRC_FAIL;
		}
		if (handlePreambleTag(spec, pkg, tag, macro, lang))
		    return RPMRC_FAIL;
		if (spec->BANames && !spec->recursing && spec->toplevel)
		    return PART_BUILDARCHITECTURES;
	    }
	    if ((rc =
		 readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
		nextPart = PART_NONE;
		break;
	    }
	    if (rc)
		return rc;
	}
    }

    /* Do some final processing on the header */

    /* 
     * Expand buildroot one more time to get %{version} and the like
     * from the main package.
     */
    if (initialPackage) {
        const char *s = rpmExpand("%{?buildroot}", NULL);
	if (s && *s) 
	    (void) addMacro(NULL, "buildroot", NULL, s, -1);
	s = _free(s);
    }
    
    /* XXX Skip valid arch check if not building binary package */
    if (!spec->anyarch && checkForValidArchitectures(spec))
	return RPMRC_FAIL;

    if (pkg == spec->packages)
	fillOutMainPackage(pkg->header);

    if (checkForDuplicates(pkg->header, NVR) != RPMRC_OK)
	return RPMRC_FAIL;

    if (pkg != spec->packages)
	headerCopyTags(spec->packages->header, pkg->header,
			(void *)copyTagsDuringParse);

#ifdef RPM_VENDOR_PLD /* rpm-epoch0 */
    /* Add Epoch: 0 to package header if it was not set by spec */
    he->tag = RPMTAG_NAME;
    if (headerGet(spec->packages->header, he, 0) == 0) {
    	rpmuint32_t num = 0;

	he->tag = RPMTAG_EPOCH;
	he->t = RPM_UINT32_TYPE;
	he->p.ui32p = &num;
	he->c = 1;
	xx = headerPut(pkg->header, he, 0);

	/* also declare %{epoch} to be same */
	addMacro(spec->macros, "epoch", NULL, "0", RMIL_SPEC);
    }
#endif /* RPM_VENDOR_PLD rpm-epoch0 */

    if (checkForRequired(pkg->header, NVR) != RPMRC_OK)
	return RPMRC_FAIL;

    return nextPart;
}
Пример #28
0
/** \ingroup rpmcli
 * Create/modify elements in signature header.
 * @param rpm		path to package
 * @param deleting	adding or deleting signature?
 * @param signfiles	sign files if non-zero
 * @return		0 on success, -1 on error
 */
static int rpmSign(const char *rpm, int deleting, int signfiles)
{
    FD_t fd = NULL;
    FD_t ofd = NULL;
    char *trpm = NULL;
    Header sigh = NULL;
    Header h = NULL;
    char *msg = NULL;
    int res = -1; /* assume failure */
    rpmRC rc;
    struct rpmtd_s utd;
    off_t headerStart;
    off_t sigStart;
    struct sigTarget_s sigt_v3;
    struct sigTarget_s sigt_v4;
    unsigned int origSigSize;
    int insSig = 0;

    fprintf(stdout, "%s:\n", rpm);

    if (manageFile(&fd, rpm, O_RDWR))
	goto exit;

    if ((rc = rpmLeadRead(fd, &msg)) != RPMRC_OK) {
	rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, msg);
	goto exit;
    }

    sigStart = Ftell(fd);
    rc = rpmReadSignature(fd, &sigh, &msg);
    if (rc != RPMRC_OK) {
	rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), rpm,
		    (msg && *msg ? msg : "\n"));
	goto exit;
    }

    headerStart = Ftell(fd);
    if (rpmReadHeader(NULL, fd, &h, &msg) != RPMRC_OK) {
	rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s\n"), rpm, msg);
	goto exit;
    }

    if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
	rpmlog(RPMLOG_ERR, _("Cannot sign RPM v3 packages\n"));
	goto exit;
    }

    unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES);
    origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);

    if (signfiles) {
	if (includeFileSignatures(&sigh, &h))
	    goto exit;
    }

    if (deleting) {	/* Nuke all the signature tags. */
	deleteSigs(sigh);
    } else {
	/* Signature target containing header + payload */
	sigt_v3.fd = fd;
	sigt_v3.start = headerStart;
	sigt_v3.fileName = rpm;
	sigt_v3.size = fdSize(fd) - headerStart;

	/* Signature target containing only header */
	sigt_v4 = sigt_v3;
	sigt_v4.size = headerSizeof(h, HEADER_MAGIC_YES);

	res = replaceSignature(sigh, &sigt_v3, &sigt_v4);
	if (res != 0) {
	    if (res == 1) {
		rpmlog(RPMLOG_WARNING,
		   _("%s already contains identical signature, skipping\n"),
		   rpm);
		/* Identical signature is not an error */
		res = 0;
	    }
	    goto exit;
	}
	res = -1;
    }

    /* Try to make new signature smaller to have size of original signature */
    rpmtdReset(&utd);
    if (headerGet(sigh, RPMSIGTAG_RESERVEDSPACE, &utd, HEADERGET_MINMEM)) {
	int diff;
	int count;
	char *reservedSpace = NULL;

	count = utd.count;
	diff = headerSizeof(sigh, HEADER_MAGIC_YES) - origSigSize;

	if (diff < count) {
	    reservedSpace = xcalloc(count - diff, sizeof(char));
	    headerDel(sigh, RPMSIGTAG_RESERVEDSPACE);
	    rpmtdReset(&utd);
	    utd.tag = RPMSIGTAG_RESERVEDSPACE;
	    utd.count = count - diff;
	    utd.type = RPM_BIN_TYPE;
	    utd.data = reservedSpace;
	    headerPut(sigh, &utd, HEADERPUT_DEFAULT);
	    free(reservedSpace);
	    insSig = 1;
	}
    }

    /* Reallocate the signature into one contiguous region. */
    sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
    if (sigh == NULL)	/* XXX can't happen */
	goto exit;

    if (insSig) {
	/* Insert new signature into original rpm */
	if (Fseek(fd, sigStart, SEEK_SET) < 0) {
	    rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
		    rpm, Fstrerror(fd));
	    goto exit;
	}

	if (rpmWriteSignature(fd, sigh)) {
	    rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n"), rpm,
		Fstrerror(fd));
	    goto exit;
	}
	res = 0;
    } else {
	/* Replace orignal rpm with new rpm containing new signature */
	rasprintf(&trpm, "%s.XXXXXX", rpm);
	ofd = rpmMkTemp(trpm);
	if (ofd == NULL || Ferror(ofd)) {
	    rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
	    goto exit;
	}

	/* Write the lead/signature of the output rpm */
	rc = rpmLeadWrite(ofd, h);
	if (rc != RPMRC_OK) {
	    rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n"), trpm,
		Fstrerror(ofd));
	    goto exit;
	}

	if (rpmWriteSignature(ofd, sigh)) {
	    rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n"), trpm,
		Fstrerror(ofd));
	    goto exit;
	}

	if (Fseek(fd, headerStart, SEEK_SET) < 0) {
	    rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
		    rpm, Fstrerror(fd));
	    goto exit;
	}
	/* Append the header and archive from the temp file */
	if (copyFile(&fd, rpm, &ofd, trpm) == 0) {
	    struct stat st;

	    /* Move final target into place, restore file permissions. */
	    if (stat(rpm, &st) == 0 && unlink(rpm) == 0 &&
			rename(trpm, rpm) == 0 && chmod(rpm, st.st_mode) == 0) {
		res = 0;
	    } else {
		rpmlog(RPMLOG_ERR, _("replacing %s failed: %s\n"),
		       rpm, strerror(errno));
	    }
	}
    }

exit:
    if (fd)	(void) closeFile(&fd);
    if (ofd)	(void) closeFile(&ofd);

    headerFree(sigh);
    headerFree(h);
    free(msg);

    /* Clean up intermediate target */
    if (trpm) {
	(void) unlink(trpm);
	free(trpm);
    }

    return res;
}
Пример #29
0
int addReqProv(/*@unused@*/ Spec spec, Header h,
		/*@unused@*/ rpmTag tagN,
		const char * N, const char * EVR, rpmsenseFlags Flags,
		rpmuint32_t index)
{
    HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
    const char ** names;
    rpmTag nametag = 0;
    rpmTag versiontag = 0;
    rpmTag flagtag = 0;
    rpmTag indextag = 0;
    int len;
    rpmsenseFlags extra = RPMSENSE_ANY;
    int xx;

    if (Flags & RPMSENSE_PROVIDES) {
	nametag = RPMTAG_PROVIDENAME;
	versiontag = RPMTAG_PROVIDEVERSION;
	flagtag = RPMTAG_PROVIDEFLAGS;
	extra = Flags & RPMSENSE_FIND_PROVIDES;
    } else if (Flags & RPMSENSE_OBSOLETES) {
	nametag = RPMTAG_OBSOLETENAME;
	versiontag = RPMTAG_OBSOLETEVERSION;
	flagtag = RPMTAG_OBSOLETEFLAGS;
    } else if (Flags & RPMSENSE_CONFLICTS) {
	nametag = RPMTAG_CONFLICTNAME;
	versiontag = RPMTAG_CONFLICTVERSION;
	flagtag = RPMTAG_CONFLICTFLAGS;
    } else if (Flags & RPMSENSE_TRIGGER) {
	nametag = RPMTAG_TRIGGERNAME;
	versiontag = RPMTAG_TRIGGERVERSION;
	flagtag = RPMTAG_TRIGGERFLAGS;
	indextag = RPMTAG_TRIGGERINDEX;
	extra = Flags & RPMSENSE_TRIGGER;
    } else {
	nametag = RPMTAG_REQUIRENAME;
	versiontag = RPMTAG_REQUIREVERSION;
	flagtag = RPMTAG_REQUIREFLAGS;
	extra = Flags & _ALL_REQUIRES_MASK;
    }

    Flags = (Flags & RPMSENSE_SENSEMASK) | extra;

    if (EVR == NULL)
	EVR = "";
#if defined(RPM_VENDOR_MANDRIVA)
    /* Check that provide isn't duplicate of package */
    else if (nametag == RPMTAG_PROVIDENAME) {
	const char *NEVR;
	size_t len;
	int duplicate;

	len = strlen(N);
	NEVR = headerSprintf(h, "%{NAME}-%|EPOCH?{%{EPOCH}:}|%{VERSION}-%{RELEASE}", NULL, NULL, NULL);
	duplicate = !strncmp(NEVR, N, len) && !strcmp(NEVR+len+1, EVR);

	_free(NEVR);

	if (duplicate)
	    return 0;
    }
#endif

    /* Check for duplicate dependencies. */
    he->tag = nametag;
    xx = headerGet(h, he, 0);
    names = he->p.argv;
    len = he->c;
    if (xx) {
	const char ** versions = NULL;
	rpmuint32_t * flags = NULL;
	rpmuint32_t * indexes = NULL;
	int duplicate = 0;

	if (flagtag) {
	    he->tag = versiontag;
	    xx = headerGet(h, he, 0);
	    versions = he->p.argv;
	    he->tag = flagtag;
	    xx = headerGet(h, he, 0);
	    flags = he->p.ui32p;
	}
	if (indextag) {
	    he->tag = indextag;
	    xx = headerGet(h, he, 0);
	    indexes = he->p.ui32p;
	}

	while (len > 0) {
	    len--;
	    if (strcmp(names[len], N))
		continue;

#if defined(RPM_VENDOR_MANDRIVA) /* filter-overlapping-dependencies */
	    /* XXX: Potential drawbacks? Need to study & discuess this one a
	     * bit further, leaving under #ifdef for now...
	     * TODO: auto-generated deps too
	     */
	    if (flagtag && versions != NULL) {
		int overlap;

		if(*EVR && !*versions[len]) {
		    overlap = 1;
		    flags[len] = Flags;
		    he->tag = flagtag;
		    he->t = RPM_UINT32_TYPE;
		    he->p.argv = (void *) &Flags;
		    xx = headerMod(h, he, 0);
		} else {
		    EVR_t lEVR = rpmEVRnew(RPMSENSE_ANY, 0),
			  rEVR = rpmEVRnew(RPMSENSE_ANY, 0);

		    rpmEVRparse(EVR, lEVR);
		    rpmEVRparse(versions[len], rEVR);
		    lEVR->Flags = Flags | RPMSENSE_EQUAL;
		    rEVR->Flags = flags[len] | RPMSENSE_EQUAL;
		    overlap = rpmEVRoverlap(lEVR, rEVR);
		    if (!overlap)
			if (rpmEVRoverlap(rEVR, lEVR))
    			    duplicate = 1;
		    lEVR = rpmEVRfree(lEVR);
		    rEVR = rpmEVRfree(rEVR);
		}
		if (overlap) {
		    versions[len] = EVR;
		    he->tag = versiontag;
		    he->t = RPM_STRING_ARRAY_TYPE;
		    he->p.argv = versions;
		    xx = headerMod(h, he, 0);
		} else
		    continue;
	    }
#else
	    if (flagtag && versions != NULL &&
		(strcmp(versions[len], EVR) || (rpmsenseFlags)flags[len] != Flags))
		continue;
#endif

	    if (indextag && indexes != NULL && indexes[len] != index)
		continue;

	    /* This is a duplicate dependency. */
	    duplicate = 1;

	    break;
	}
/*@-usereleased@*/
	names = _free(names);
	versions = _free(versions);
	flags = _free(flags);
	indexes = _free(indexes);
/*@=usereleased@*/
	if (duplicate)
	    return 0;
    }

    /* Add this dependency. */
    he->tag = nametag;
    he->t = RPM_STRING_ARRAY_TYPE;
    he->p.argv = &N;
    he->c = 1;
    he->append = 1;
    xx = headerPut(h, he, 0);
    he->append = 0;

    if (flagtag) {
	he->tag = versiontag;
	he->t = RPM_STRING_ARRAY_TYPE;
	he->p.argv = &EVR;
	he->c = 1;
	he->append = 1;
	xx = headerPut(h, he, 0);
	he->append = 0;

	he->tag = flagtag;
	he->t = RPM_UINT32_TYPE;
	he->p.ui32p = (void *) &Flags;
	he->c = 1;
	he->append = 1;
	xx = headerPut(h, he, 0);
	he->append = 0;
    }
    if (indextag) {
	he->tag = indextag;
	he->t = RPM_UINT32_TYPE;
	he->p.ui32p = &index;
	he->c = 1;
	he->append = 1;
	xx = headerPut(h, he, 0);
	he->append = 0;
    }

    return 0;
}
Пример #30
0
int parseScript(rpmSpec spec, int parsePart)
{
    /* There are a few options to scripts: */
    /*  <pkg>                              */
    /*  -n <pkg>                           */
    /*  -p <sh>                            */
    /*  -p "<sh> <args>..."                */
    /*  -f <file>                          */

    const char *p;
    const char **progArgv = NULL;
    int progArgc;
    const char *partname = NULL;
    rpmTagVal reqtag = 0;
    rpmTagVal tag = 0;
    rpmsenseFlags tagflags = 0;
    rpmTagVal progtag = 0;
    rpmTagVal flagtag = 0;
    rpmscriptFlags scriptFlags = 0;
    int flag = PART_SUBNAME;
    Package pkg;
    StringBuf sb = NULL;
    int nextPart;
    int index;
    char * reqargs = NULL;

    int res = PART_ERROR; /* assume failure */
    int rc, argc;
    int arg;
    const char **argv = NULL;
    poptContext optCon = NULL;
    const char *name = NULL;
    const char *prog = "/bin/sh";
    const char *file = NULL;
    struct poptOption optionsTable[] = {
	{ NULL, 'p', POPT_ARG_STRING, &prog, 'p',	NULL, NULL},
	{ NULL, 'n', POPT_ARG_STRING, &name, 'n',	NULL, NULL},
	{ NULL, 'f', POPT_ARG_STRING, &file, 'f',	NULL, NULL},
	{ NULL, 'e', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_EXPAND,
	  NULL, NULL},
	{ NULL, 'q', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_QFORMAT,
	  NULL, NULL},
	{ 0, 0, 0, 0, 0,	NULL, NULL}
    };

    switch (parsePart) {
      case PART_PRE:
	tag = RPMTAG_PREIN;
	tagflags = RPMSENSE_SCRIPT_PRE;
	progtag = RPMTAG_PREINPROG;
	flagtag = RPMTAG_PREINFLAGS;
	partname = "%pre";
	break;
      case PART_POST:
	tag = RPMTAG_POSTIN;
	tagflags = RPMSENSE_SCRIPT_POST;
	progtag = RPMTAG_POSTINPROG;
	flagtag = RPMTAG_POSTINFLAGS;
	partname = "%post";
	break;
      case PART_PREUN:
	tag = RPMTAG_PREUN;
	tagflags = RPMSENSE_SCRIPT_PREUN;
	progtag = RPMTAG_PREUNPROG;
	flagtag = RPMTAG_PREUNFLAGS;
	partname = "%preun";
	break;
      case PART_POSTUN:
	tag = RPMTAG_POSTUN;
	tagflags = RPMSENSE_SCRIPT_POSTUN;
	progtag = RPMTAG_POSTUNPROG;
	flagtag = RPMTAG_POSTUNFLAGS;
	partname = "%postun";
	break;
      case PART_PRETRANS:
	tag = RPMTAG_PRETRANS;
	tagflags = RPMSENSE_PRETRANS;
	progtag = RPMTAG_PRETRANSPROG;
	flagtag = RPMTAG_PRETRANSFLAGS;
	partname = "%pretrans";
	break;
      case PART_POSTTRANS:
	tag = RPMTAG_POSTTRANS;
	tagflags = RPMSENSE_POSTTRANS;
	progtag = RPMTAG_POSTTRANSPROG;
	flagtag = RPMTAG_POSTTRANSFLAGS;
	partname = "%posttrans";
	break;
      case PART_VERIFYSCRIPT:
	tag = RPMTAG_VERIFYSCRIPT;
	tagflags = RPMSENSE_SCRIPT_VERIFY;
	progtag = RPMTAG_VERIFYSCRIPTPROG;
	flagtag = RPMTAG_VERIFYSCRIPTFLAGS;
	partname = "%verifyscript";
	break;
      case PART_TRIGGERPREIN:
	tag = RPMTAG_TRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRIGGERPREIN;
	progtag = RPMTAG_TRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRIGGERSCRIPTFLAGS;
	partname = "%triggerprein";
	break;
      case PART_TRIGGERIN:
	tag = RPMTAG_TRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRIGGERIN;
	progtag = RPMTAG_TRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRIGGERSCRIPTFLAGS;
	partname = "%triggerin";
	break;
      case PART_TRIGGERUN:
	tag = RPMTAG_TRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRIGGERUN;
	progtag = RPMTAG_TRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRIGGERSCRIPTFLAGS;
	partname = "%triggerun";
	break;
      case PART_TRIGGERPOSTUN:
	tag = RPMTAG_TRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRIGGERPOSTUN;
	progtag = RPMTAG_TRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRIGGERSCRIPTFLAGS;
	partname = "%triggerpostun";
	break;
      case PART_FILETRIGGERIN:
	tag = RPMTAG_FILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_FILETRIGGERIN;
	progtag = RPMTAG_FILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS;
	partname = "%filetriggerin";
	break;
      case PART_FILETRIGGERUN:
	tag = RPMTAG_FILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_FILETRIGGERUN;
	progtag = RPMTAG_FILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS;
	partname = "%filetriggerun";
	break;
      case PART_FILETRIGGERPOSTUN:
	tag = RPMTAG_FILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_FILETRIGGERPOSTUN;
	progtag = RPMTAG_FILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS;
	partname = "%filetriggerpostun";
	break;
      case PART_TRANSFILETRIGGERIN:
	tag = RPMTAG_TRANSFILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRANSFILETRIGGERIN;
	progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS;
	partname = "%transfiletriggerin";
	break;
      case PART_TRANSFILETRIGGERUN:
	tag = RPMTAG_TRANSFILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRANSFILETRIGGERUN;
	progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS;
	partname = "%transfiletriggerun";
	break;
      case PART_TRANSFILETRIGGERPOSTUN:
	tag = RPMTAG_TRANSFILETRIGGERSCRIPTS;
	tagflags = 0;
	reqtag = RPMTAG_TRANSFILETRIGGERPOSTUN;
	progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG;
	flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS;
	partname = "%transfiletriggerpostun";
	break;
    }

    if (tag == RPMTAG_TRIGGERSCRIPTS || tag == RPMTAG_FILETRIGGERSCRIPTS ||
	tag == RPMTAG_TRANSFILETRIGGERSCRIPTS) {
	/* break line into two */
	char *s = strstr(spec->line, "--");
	if (!s) {
	    rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"),
		     spec->lineNum, spec->line);
	    return PART_ERROR;
	}

	*s = '\0';
	reqargs = xstrdup(s + 2);
    }
    
    if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
	rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
		 spec->lineNum, partname, poptStrerror(rc));
	goto exit;
    }
    
    optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
    while ((arg = poptGetNextOpt(optCon)) > 0) {
	switch (arg) {
	case 'p':
	    if (prog[0] == '<') {
		if (prog[strlen(prog)-1] != '>') {
		    rpmlog(RPMLOG_ERR,
			     _("line %d: internal script must end "
			     "with \'>\': %s\n"), spec->lineNum, prog);
		    goto exit;
		}
	    } else if (prog[0] != '/') {
		rpmlog(RPMLOG_ERR,
			 _("line %d: script program must begin "
			 "with \'/\': %s\n"), spec->lineNum, prog);
		goto exit;
	    }
	    break;
	case 'n':
	    flag = PART_NAME;
	    break;
	}
    }
    
    if (arg < -1) {
	rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"),
		 spec->lineNum,
		 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
		 spec->line);
	goto exit;
    }

    if (poptPeekArg(optCon)) {
	if (name == NULL)
	    name = poptGetArg(optCon);
	if (poptPeekArg(optCon)) {
	    rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"),
		     spec->lineNum,
		     spec->line);
	    goto exit;
	}
    }
    
    if (lookupPackage(spec, name, flag, &pkg)) {
	rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"),
		 spec->lineNum, spec->line);
	goto exit;
    }

    if (tag != RPMTAG_TRIGGERSCRIPTS) {
	if (headerIsEntry(pkg->header, progtag)) {
	    rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"),
		     spec->lineNum, partname);
	    goto exit;
	}
    }

    if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
	rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"),
		 spec->lineNum, partname, poptStrerror(rc));
	goto exit;
    }

    sb = newStringBuf();
    if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
	nextPart = PART_NONE;
    } else if (rc < 0) {
	goto exit;
    } else {
	while (! (nextPart = isPart(spec->line))) {
	    appendStringBuf(sb, spec->line);
	    if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
		nextPart = PART_NONE;
		break;
	    } else if (rc < 0) {
		goto exit;
	    }
	}
    }
    stripTrailingBlanksStringBuf(sb);
    p = getStringBuf(sb);

#ifdef WITH_LUA
    if (rstreq(progArgv[0], "<lua>")) {
	rpmlua lua = NULL; /* Global state. */
	if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) {
	    goto exit;
	}
	(void) rpmlibNeedsFeature(pkg, "BuiltinLuaScripts", "4.2.2-1");
    } else
#endif
    if (progArgv[0][0] == '<') {
	rpmlog(RPMLOG_ERR,
		 _("line %d: unsupported internal script: %s\n"),
		 spec->lineNum, progArgv[0]);
	goto exit;
    } else {
        (void) addReqProv(pkg, RPMTAG_REQUIRENAME,
		progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0);
    }

    if (scriptFlags) {
	rpmlibNeedsFeature(pkg, "ScriptletExpansion", "4.9.0-1");
    }

    /* Trigger script insertion is always delayed in order to */
    /* get the index right.                                   */
    if (tag == RPMTAG_TRIGGERSCRIPTS || tag == RPMTAG_FILETRIGGERSCRIPTS ||
	tag == RPMTAG_TRANSFILETRIGGERSCRIPTS) {
	if (progArgc > 1) {
	    rpmlog(RPMLOG_ERR,
	      _("line %d: interpreter arguments not allowed in triggers: %s\n"),
	      spec->lineNum, prog);
	    goto exit;
	}
	/* Add file/index/prog triple to the trigger file list */
	index = addTriggerIndex(pkg, file, p, progArgv[0], scriptFlags, tag);

	/* Generate the trigger tags */
	if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags))
	    goto exit;
    } else {
	struct rpmtd_s td;

	/*
 	 * XXX Ancient rpm uses STRING, not STRING_ARRAY type here. Construct
 	 * the td manually and preserve legacy compat for now...
 	 */
	rpmtdReset(&td);
	td.tag = progtag;
	td.count = progArgc;
	if (progArgc == 1) {
	    td.data = (void *) *progArgv;
	    td.type = RPM_STRING_TYPE;
	} else {
	    (void) rpmlibNeedsFeature(pkg,
			"ScriptletInterpreterArgs", "4.0.3-1");
	    td.data = progArgv;
	    td.type = RPM_STRING_ARRAY_TYPE;
	}
	headerPut(pkg->header, &td, HEADERPUT_DEFAULT);

	if (*p != '\0') {
	    headerPutString(pkg->header, tag, p);
	}
	if (scriptFlags) {
	    headerPutUint32(pkg->header, flagtag, &scriptFlags, 1);
	}

	if (file) {
	    switch (parsePart) {
	      case PART_PRE:
		pkg->preInFile = xstrdup(file);
		break;
	      case PART_POST:
		pkg->postInFile = xstrdup(file);
		break;
	      case PART_PREUN:
		pkg->preUnFile = xstrdup(file);
		break;
	      case PART_POSTUN:
		pkg->postUnFile = xstrdup(file);
		break;
	      case PART_PRETRANS:
		pkg->preTransFile = xstrdup(file);
		break;
	      case PART_POSTTRANS:
		pkg->postTransFile = xstrdup(file);
		break;
	      case PART_VERIFYSCRIPT:
		pkg->verifyFile = xstrdup(file);
		break;
	    }
	}
    }
    res = nextPart;
    
exit:
    free(reqargs);
    freeStringBuf(sb);
    free(progArgv);
    free(argv);
    poptFreeContext(optCon);
    
    return res;
}