csomh / source-git / rpm

Forked from source-git/rpm 4 years ago
Clone
2ff057
/** \ingroup rpmbuild
2ff057
 * \file build/spec.c
2ff057
 * Handle spec data structure.
2ff057
 */
2ff057
2ff057
#include "system.h"
2ff057
2ff057
#include <rpm/header.h>
2ff057
#include <rpm/rpmds.h>
2ff057
#include <rpm/rpmfi.h>
2ff057
#include <rpm/rpmts.h>
2ff057
#include <rpm/rpmlog.h>
2ff057
#include <rpm/rpmfileutil.h>
2ff057
2ff057
#include "rpmio/rpmlua.h"
2ff057
#include "lib/rpmfi_internal.h"		/* rpmfiles stuff */
2ff057
#include "build/rpmbuild_internal.h"
2ff057
2ff057
#include "debug.h"
2ff057
2ff057
#define SKIPSPACE(s) { while (*(s) && risspace(*(s))) (s)++; }
2ff057
2ff057
/**
2ff057
 * @param p		trigger entry chain
2ff057
 * @return		NULL always
2ff057
 */
2ff057
static inline
2ff057
struct TriggerFileEntry * freeTriggerFiles(struct TriggerFileEntry * p)
2ff057
{
2ff057
    struct TriggerFileEntry *o, *q = p;
2ff057
    
2ff057
    while (q != NULL) {
2ff057
	o = q;
2ff057
	q = q->next;
2ff057
	o->fileName = _free(o->fileName);
2ff057
	o->script = _free(o->script);
2ff057
	o->prog = _free(o->prog);
2ff057
	free(o);
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
/**
2ff057
 * Destroy source component chain.
2ff057
 * @param s		source component chain
2ff057
 * @return		NULL always
2ff057
 */
2ff057
static inline
2ff057
struct Source * freeSources(struct Source * s)
2ff057
{
2ff057
    struct Source *r, *t = s;
2ff057
2ff057
    while (t != NULL) {
2ff057
	r = t;
2ff057
	t = t->next;
2ff057
	r->fullSource = _free(r->fullSource);
2ff057
	free(r);
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
rpmRC lookupPackage(rpmSpec spec, const char *name, int flag,Package *pkg)
2ff057
{
2ff057
    char *fullName = NULL;
2ff057
    rpmsid nameid = 0;
2ff057
    Package p;
2ff057
2ff057
    /* "main" package */
2ff057
    if (name == NULL) {
2ff057
	if (pkg)
2ff057
	    *pkg = spec->packages;
2ff057
	return RPMRC_OK;
2ff057
    }
2ff057
2ff057
    /* Construct partial package name */
2ff057
    if (!(flag & PART_NAME)) {
2ff057
	rasprintf(&fullName, "%s-%s",
2ff057
		 headerGetString(spec->packages->header, RPMTAG_NAME), name);
2ff057
	name = fullName;
2ff057
    }
2ff057
    nameid = rpmstrPoolId(spec->pool, name, 1);
2ff057
2ff057
    /* Locate package the name */
2ff057
    for (p = spec->packages; p != NULL; p = p->next) {
2ff057
	if (p->name && p->name == nameid) {
2ff057
	    break;
2ff057
	}
2ff057
    }
2ff057
2ff057
    if (!(flag & PART_QUIET)) {
2ff057
	if (p == NULL && pkg != NULL) {
2ff057
	    rpmlog(RPMLOG_ERR, _("line %d: %s: package %s does not exist\n"),
2ff057
				    spec->lineNum, spec->line, name);
2ff057
	} else if (p != NULL && pkg == NULL) {
2ff057
	    rpmlog(RPMLOG_ERR, _("line %d: %s: package %s already exists\n"),
2ff057
				    spec->lineNum, spec->line, name);
2ff057
	}
2ff057
    }
2ff057
2ff057
    if (fullName == name)
2ff057
	free(fullName);
2ff057
2ff057
    if (pkg)
2ff057
	*pkg = p;
2ff057
    return ((p == NULL) ? RPMRC_FAIL : RPMRC_OK);
2ff057
}
2ff057
2ff057
Package newPackage(const char *name, rpmstrPool pool, Package *pkglist)
2ff057
{
2ff057
    Package p = xcalloc(1, sizeof(*p));
2ff057
    p->header = headerNew();
2ff057
    p->autoProv = 1;
2ff057
    p->autoReq = 1;
2ff057
    p->fileList = NULL;
2ff057
    p->fileExcludeList = NULL;
2ff057
    p->fileFile = NULL;
2ff057
    p->policyList = NULL;
2ff057
    p->fileRenameMap = NULL;
2ff057
    p->pool = rpmstrPoolLink(pool);
2ff057
    p->dpaths = NULL;
2ff057
2ff057
    if (name)
2ff057
	p->name = rpmstrPoolId(p->pool, name, 1);
2ff057
2ff057
    if (pkglist) {
2ff057
	if (*pkglist == NULL) {
2ff057
	    *pkglist = p;
2ff057
	} else {
2ff057
	    Package pp;
2ff057
	    /* Always add package to end of list */
2ff057
	    for (pp = *pkglist; pp->next != NULL; pp = pp->next)
2ff057
		{};
2ff057
	    pp->next = p;
2ff057
	}
2ff057
    }
2ff057
    p->next = NULL;
2ff057
2ff057
    return p;
2ff057
}
2ff057
2ff057
static Package freePackage(Package pkg)
2ff057
{
2ff057
    if (pkg == NULL) return NULL;
2ff057
    
2ff057
    pkg->preInFile = _free(pkg->preInFile);
2ff057
    pkg->postInFile = _free(pkg->postInFile);
2ff057
    pkg->preUnFile = _free(pkg->preUnFile);
2ff057
    pkg->postUnFile = _free(pkg->postUnFile);
2ff057
    pkg->verifyFile = _free(pkg->verifyFile);
2ff057
2ff057
    pkg->header = headerFree(pkg->header);
2ff057
    pkg->ds = rpmdsFree(pkg->ds);
2ff057
2ff057
    for (int i=0; i
2ff057
	pkg->dependencies[i] = rpmdsFree(pkg->dependencies[i]);
2ff057
    }
2ff057
2ff057
    pkg->fileList = argvFree(pkg->fileList);
2ff057
    pkg->fileExcludeList = argvFree(pkg->fileExcludeList);
2ff057
    pkg->fileFile = argvFree(pkg->fileFile);
2ff057
    pkg->policyList = argvFree(pkg->policyList);
2ff057
    pkg->removePostfixes = argvFree(pkg->removePostfixes);
2ff057
    pkg->fileRenameMap = fileRenameHashFree(pkg->fileRenameMap);
2ff057
    pkg->cpioList = rpmfilesFree(pkg->cpioList);
2ff057
    pkg->dpaths = argvFree(pkg->dpaths);
2ff057
2ff057
    pkg->icon = freeSources(pkg->icon);
2ff057
    pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
2ff057
    pkg->fileTriggerFiles = freeTriggerFiles(pkg->fileTriggerFiles);
2ff057
    pkg->transFileTriggerFiles = freeTriggerFiles(pkg->transFileTriggerFiles);
2ff057
    pkg->pool = rpmstrPoolFree(pkg->pool);
2ff057
2ff057
    free(pkg);
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
static Package freePackages(Package packages)
2ff057
{
2ff057
    Package p;
2ff057
2ff057
    while ((p = packages) != NULL) {
2ff057
	packages = p->next;
2ff057
	p->next = NULL;
2ff057
	freePackage(p);
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
rpmds * packageDependencies(Package pkg, rpmTagVal tag)
2ff057
{
2ff057
    for (int i=0; i
2ff057
	if (pkg->dependencies[i] == NULL) {
2ff057
	    return &pkg->dependencies[i];
2ff057
	}
2ff057
	rpmTagVal tagN = rpmdsTagN(pkg->dependencies[i]);
2ff057
	if (tagN == tag || tagN == 0) {
2ff057
	    return &pkg->dependencies[i];
2ff057
	}
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
2ff057
rpmSpec newSpec(void)
2ff057
{
2ff057
    rpmSpec spec = xcalloc(1, sizeof(*spec));
2ff057
    
2ff057
    spec->specFile = NULL;
2ff057
2ff057
    spec->fileStack = NULL;
2ff057
    spec->lbufSize = BUFSIZ * 10;
2ff057
    spec->lbuf = xmalloc(spec->lbufSize);
2ff057
    spec->lbuf[0] = '\0';
2ff057
    spec->line = spec->lbuf;
2ff057
    spec->nextline = NULL;
2ff057
    spec->nextpeekc = '\0';
2ff057
    spec->lineNum = 0;
2ff057
    spec->readStack = xcalloc(1, sizeof(*spec->readStack));
2ff057
    spec->readStack->next = NULL;
2ff057
    spec->readStack->reading = 1;
2ff057
2ff057
    spec->rootDir = NULL;
2ff057
    spec->prep = NULL;
2ff057
    spec->build = NULL;
2ff057
    spec->install = NULL;
2ff057
    spec->check = NULL;
2ff057
    spec->clean = NULL;
2ff057
    spec->parsed = NULL;
2ff057
2ff057
    spec->sources = NULL;
2ff057
    spec->packages = NULL;
2ff057
    spec->noSource = 0;
2ff057
    spec->numSources = 0;
2ff057
2ff057
    spec->sourceRpmName = NULL;
2ff057
    spec->sourcePkgId = NULL;
2ff057
    spec->sourcePackage = NULL;
2ff057
    
2ff057
    spec->buildRoot = NULL;
2ff057
    spec->buildSubdir = NULL;
2ff057
2ff057
    spec->buildRestrictions = headerNew();
2ff057
    spec->BANames = NULL;
2ff057
    spec->BACount = 0;
2ff057
    spec->recursing = 0;
2ff057
    spec->BASpecs = NULL;
2ff057
2ff057
    spec->flags = RPMSPEC_NONE;
2ff057
2ff057
    spec->macros = rpmGlobalMacroContext;
2ff057
    spec->pool = rpmstrPoolCreate();
2ff057
    
2ff057
#ifdef WITH_LUA
2ff057
    {
2ff057
    /* make sure patches and sources tables always exist */
2ff057
    rpmlua lua = NULL; /* global state */
2ff057
    rpmluaDelVar(lua, "patches");
2ff057
    rpmluaDelVar(lua, "sources");
2ff057
    rpmluaPushTable(lua, "patches");
2ff057
    rpmluaPushTable(lua, "sources");
2ff057
    rpmluaPop(lua);
2ff057
    rpmluaPop(lua);
2ff057
    }
2ff057
#endif
2ff057
    return spec;
2ff057
}
2ff057
2ff057
rpmSpec rpmSpecFree(rpmSpec spec)
2ff057
{
2ff057
2ff057
    if (spec == NULL) return NULL;
2ff057
2ff057
    spec->prep = freeStringBuf(spec->prep);
2ff057
    spec->build = freeStringBuf(spec->build);
2ff057
    spec->install = freeStringBuf(spec->install);
2ff057
    spec->check = freeStringBuf(spec->check);
2ff057
    spec->clean = freeStringBuf(spec->clean);
2ff057
    spec->parsed = freeStringBuf(spec->parsed);
2ff057
2ff057
    spec->buildRoot = _free(spec->buildRoot);
2ff057
    spec->buildSubdir = _free(spec->buildSubdir);
2ff057
    spec->specFile = _free(spec->specFile);
2ff057
2ff057
    closeSpec(spec);
2ff057
2ff057
    while (spec->readStack) {
2ff057
	struct ReadLevelEntry *rl = spec->readStack;
2ff057
	spec->readStack = rl->next;
2ff057
	rl->next = NULL;
2ff057
	free(rl);
2ff057
    }
2ff057
    spec->lbuf = _free(spec->lbuf);
2ff057
    
2ff057
    spec->sourceRpmName = _free(spec->sourceRpmName);
2ff057
    spec->sourcePkgId = _free(spec->sourcePkgId);
2ff057
    spec->sourcePackage = freePackage(spec->sourcePackage);
2ff057
2ff057
    spec->buildRestrictions = headerFree(spec->buildRestrictions);
2ff057
2ff057
    if (!spec->recursing) {
2ff057
	if (spec->BASpecs != NULL)
2ff057
	while (spec->BACount--) {
2ff057
	    spec->BASpecs[spec->BACount] =
2ff057
			rpmSpecFree(spec->BASpecs[spec->BACount]);
2ff057
	}
2ff057
	spec->BASpecs = _free(spec->BASpecs);
2ff057
    }
2ff057
    spec->BANames = _free(spec->BANames);
2ff057
2ff057
#ifdef WITH_LUA
2ff057
    // only destroy lua tables if there are no BASpecs left
2ff057
    if (spec->recursing || spec->BACount == 0) {
2ff057
    rpmlua lua = NULL; /* global state */
2ff057
    rpmluaDelVar(lua, "patches");
2ff057
    rpmluaDelVar(lua, "sources");	
2ff057
    }
2ff057
#endif
2ff057
2ff057
    spec->sources = freeSources(spec->sources);
2ff057
    spec->packages = freePackages(spec->packages);
2ff057
    spec->pool = rpmstrPoolFree(spec->pool);
2ff057
    
2ff057
    spec = _free(spec);
2ff057
2ff057
    return spec;
2ff057
}
2ff057
2ff057
Header rpmSpecSourceHeader(rpmSpec spec)
2ff057
{
2ff057
    return (spec && spec->sourcePackage) ? spec->sourcePackage->header : NULL;
2ff057
}
2ff057
2ff057
rpmds rpmSpecDS(rpmSpec spec, rpmTagVal tag)
2ff057
{
2ff057
    return (spec != NULL) ? rpmdsNew(spec->sourcePackage->header, tag, 0) : NULL;
2ff057
}
2ff057
2ff057
rpmps rpmSpecCheckDeps(rpmts ts, rpmSpec spec)
2ff057
{
2ff057
    rpmps probs = NULL;
2ff057
2ff057
    rpmtsEmpty(ts);
2ff057
2ff057
    rpmtsAddInstallElement(ts, rpmSpecSourceHeader(spec), NULL, 0, NULL);
2ff057
    rpmtsCheck(ts);
2ff057
    probs = rpmtsProblems(ts);
2ff057
2ff057
    rpmtsEmpty(ts);
2ff057
    return probs;
2ff057
}
2ff057
2ff057
struct rpmSpecIter_s {
2ff057
    void *next;
2ff057
};
2ff057
2ff057
#define SPEC_LISTITER_INIT(_itertype, _iteritem)	\
2ff057
    _itertype iter = NULL;				\
2ff057
    if (spec) {						\
2ff057
	iter = xcalloc(1, sizeof(*iter));		\
2ff057
	iter->next = spec->_iteritem;			\
2ff057
    }							\
2ff057
    return iter
2ff057
2ff057
#define SPEC_LISTITER_NEXT(_valuetype)			\
2ff057
    _valuetype item = NULL;				\
2ff057
    if (iter) {						\
2ff057
	item = iter->next;				\
2ff057
	iter->next = (item) ? item->next : NULL;	\
2ff057
    }							\
2ff057
    return item
2ff057
2ff057
#define SPEC_LISTITER_FREE()				\
2ff057
    free(iter);						\
2ff057
    return NULL
2ff057
2ff057
2ff057
rpmSpecPkgIter rpmSpecPkgIterInit(rpmSpec spec)
2ff057
{
2ff057
    SPEC_LISTITER_INIT(rpmSpecPkgIter, packages);
2ff057
}
2ff057
2ff057
rpmSpecPkgIter rpmSpecPkgIterFree(rpmSpecPkgIter iter)
2ff057
{
2ff057
    SPEC_LISTITER_FREE();
2ff057
}
2ff057
2ff057
rpmSpecPkg rpmSpecPkgIterNext(rpmSpecPkgIter iter)
2ff057
{
2ff057
    SPEC_LISTITER_NEXT(rpmSpecPkg);
2ff057
}
2ff057
2ff057
Header rpmSpecPkgHeader(rpmSpecPkg pkg)
2ff057
{
2ff057
    return (pkg != NULL) ? pkg->header : NULL;
2ff057
}
2ff057
2ff057
char* rpmSpecPkgGetSection(rpmSpecPkg pkg, int section)
2ff057
{
2ff057
    if (pkg) {
2ff057
        switch (section) {
2ff057
        case RPMBUILD_FILE_FILE: return argvJoin(pkg->fileFile, "");
2ff057
        case RPMBUILD_FILE_LIST: return argvJoin(pkg->fileList, "");
2ff057
        case RPMBUILD_POLICY:    return argvJoin(pkg->policyList, "");
2ff057
        }
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
rpmSpecSrcIter rpmSpecSrcIterInit(rpmSpec spec)
2ff057
{
2ff057
    SPEC_LISTITER_INIT(rpmSpecSrcIter, sources);
2ff057
}
2ff057
2ff057
rpmSpecSrcIter rpmSpecSrcIterFree(rpmSpecSrcIter iter)
2ff057
{
2ff057
    SPEC_LISTITER_FREE();
2ff057
}
2ff057
2ff057
rpmSpecSrc rpmSpecSrcIterNext(rpmSpecSrcIter iter)
2ff057
{
2ff057
    SPEC_LISTITER_NEXT(rpmSpecSrc);
2ff057
}
2ff057
2ff057
rpmSourceFlags rpmSpecSrcFlags(rpmSpecSrc src)
2ff057
{
2ff057
    return (src != NULL) ? src->flags : 0;
2ff057
}
2ff057
2ff057
int rpmSpecSrcNum(rpmSpecSrc src)
2ff057
{
2ff057
    return (src != NULL) ? src->num : -1;
2ff057
}
2ff057
2ff057
const char * rpmSpecSrcFilename(rpmSpecSrc src, int full)
2ff057
{
2ff057
    const char *source = NULL;
2ff057
    if (src) {
2ff057
	source = full ? src->fullSource : src->source;
2ff057
    }
2ff057
    return source;
2ff057
}
2ff057
2ff057
const char * rpmSpecGetSection(rpmSpec spec, int section)
2ff057
{
2ff057
    if (spec) {
2ff057
	switch (section) {
2ff057
	case RPMBUILD_NONE:	return getStringBuf(spec->parsed);
2ff057
	case RPMBUILD_PREP:	return getStringBuf(spec->prep);
2ff057
	case RPMBUILD_BUILD:	return getStringBuf(spec->build);
2ff057
	case RPMBUILD_INSTALL:	return getStringBuf(spec->install);
2ff057
	case RPMBUILD_CHECK:	return getStringBuf(spec->check);
2ff057
	case RPMBUILD_CLEAN:	return getStringBuf(spec->clean);
2ff057
	}
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
2ff057
{
2ff057
    rpmSpec spec = NULL;
2ff057
    int res = 1;
2ff057
2ff057
    if (qva->qva_showPackage == NULL)
2ff057
	goto exit;
2ff057
2ff057
    spec = rpmSpecParse(arg, (RPMSPEC_ANYARCH|RPMSPEC_FORCE), NULL);
2ff057
    if (spec == NULL) {
2ff057
	rpmlog(RPMLOG_ERR,
2ff057
	    		_("query of specfile %s failed, can't parse\n"), arg);
2ff057
	goto exit;
2ff057
    }
2ff057
2ff057
    if (qva->qva_source == RPMQV_SPECRPMS ||
2ff057
	    qva->qva_source == RPMQV_SPECBUILTRPMS) {
2ff057
2ff057
	res = 0;
2ff057
	for (Package pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
2ff057
2ff057
	    if (qva->qva_source == RPMQV_SPECBUILTRPMS && pkg->fileList == NULL)
2ff057
		continue;
2ff057
2ff057
	    res += qva->qva_showPackage(qva, ts, pkg->header);
2ff057
	}
2ff057
    } else {
2ff057
	Package sourcePkg = spec->sourcePackage;
2ff057
	res = qva->qva_showPackage(qva, ts, sourcePkg->header);
2ff057
    }
2ff057
2ff057
exit:
2ff057
    rpmSpecFree(spec);
2ff057
    return res;
2ff057
}