3 * Handle spec data structure.
8 #include <rpm/header.h>
10 #include <rpm/rpmfi.h>
11 #include <rpm/rpmts.h>
12 #include <rpm/rpmlog.h>
13 #include <rpm/rpmfileutil.h>
15 #include "build/buildio.h"
16 #include "rpmio/rpmlua.h"
20 #define SKIPSPACE(s) { while (*(s) && risspace(*(s))) (s)++; }
21 #define SKIPWHITE(_x) {while(*(_x) && (risspace(*_x) || *(_x) == ',')) (_x)++;}
22 #define SKIPNONWHITE(_x){while(*(_x) &&!(risspace(*_x) || *(_x) == ',')) (_x)++;}
25 * @param p trigger entry chain
29 struct TriggerFileEntry * freeTriggerFiles(struct TriggerFileEntry * p)
31 struct TriggerFileEntry *o, *q = p;
36 o->fileName = _free(o->fileName);
37 o->script = _free(o->script);
38 o->prog = _free(o->prog);
45 * Destroy source component chain.
46 * @param s source component chain
50 struct Source * freeSources(struct Source * s)
52 struct Source *r, *t = s;
57 r->fullSource = _free(r->fullSource);
63 rpmRC lookupPackage(rpmSpec spec, const char *name, int flag,Package *pkg)
66 char *fullName = NULL;
72 *pkg = spec->packages;
76 /* Construct package name */
77 if (flag == PART_SUBNAME) {
78 pname = headerGetString(spec->packages->header, RPMTAG_NAME);
79 rasprintf(&fullName, "%s-%s", pname, name);
81 fullName = xstrdup(name);
84 /* Locate package with fullName */
85 for (p = spec->packages; p != NULL; p = p->next) {
86 pname = headerGetString(p->header, RPMTAG_NAME);
87 if (pname && (rstreq(fullName, pname))) {
95 return ((p == NULL) ? RPMRC_FAIL : RPMRC_OK);
98 Package newPackage(rpmSpec spec)
103 p = xcalloc(1, sizeof(*p));
105 p->header = headerNew();
115 p->triggerScripts = NULL;
118 p->triggerFiles = NULL;
126 p->postInFile = NULL;
128 p->postUnFile = NULL;
129 p->verifyFile = NULL;
131 p->specialDoc = NULL;
132 p->specialDocDir = NULL;
134 if (spec->packages == NULL) {
137 /* Always add package to end of list */
138 for (pp = spec->packages; pp->next != NULL; pp = pp->next)
147 Package freePackage(Package pkg)
149 if (pkg == NULL) return NULL;
151 pkg->preInFile = _free(pkg->preInFile);
152 pkg->postInFile = _free(pkg->postInFile);
153 pkg->preUnFile = _free(pkg->preUnFile);
154 pkg->postUnFile = _free(pkg->postUnFile);
155 pkg->verifyFile = _free(pkg->verifyFile);
157 pkg->header = headerFree(pkg->header);
158 pkg->ds = rpmdsFree(pkg->ds);
159 pkg->fileList = freeStringBuf(pkg->fileList);
160 pkg->fileFile = freeStringBuf(pkg->fileFile);
162 rpmfi fi = pkg->cpioList;
163 pkg->cpioList = NULL;
167 pkg->specialDoc = freeStringBuf(pkg->specialDoc);
168 pkg->specialDocDir = _free(pkg->specialDocDir);
169 pkg->icon = freeSources(pkg->icon);
170 pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
176 Package freePackages(Package packages)
180 while ((p = packages) != NULL) {
190 static inline struct Source *findSource(rpmSpec spec, uint32_t num, int flag)
194 for (p = spec->sources; p != NULL; p = p->next)
195 if ((num == p->num) && (p->flags & flag)) return p;
200 int parseNoSource(rpmSpec spec, const char * field, rpmTag tag)
207 if (tag == RPMTAG_NOSOURCE) {
208 flag = RPMBUILD_ISSOURCE;
211 flag = RPMBUILD_ISPATCH;
216 for (f = fe; *f != '\0'; f = fe) {
224 if (*fe != '\0') fe++;
226 if (parseUnsignedNum(f, &num)) {
227 rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
232 if (! (p = findSource(spec, num, flag))) {
233 rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %u\n"),
234 spec->lineNum, name, num);
238 p->flags |= RPMBUILD_ISNO;
245 int addSource(rpmSpec spec, Package pkg, const char *field, rpmTag tag)
249 const char *name = NULL;
257 flag = RPMBUILD_ISSOURCE;
259 fieldp = spec->line + 6;
262 flag = RPMBUILD_ISPATCH;
264 fieldp = spec->line + 5;
267 flag = RPMBUILD_ISICON;
276 if (tag != RPMTAG_ICON) {
277 /* We already know that a ':' exists, and that there */
278 /* are no spaces before it. */
279 /* This also now allows for spaces and tabs between */
280 /* the number and the ':' */
282 char *fieldp_backup = fieldp;
284 while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t')) {
290 nump = fieldp_backup;
292 if (nump == NULL || *nump == '\0') {
293 num = flag == RPMBUILD_ISSOURCE ? 0 : INT_MAX;
295 if (parseUnsignedNum(fieldp_backup, &num)) {
296 rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
297 spec->lineNum, name, spec->line);
305 /* Check whether tags of the same number haven't already been defined */
306 for (p = spec->sources; p != NULL; p = p->next) {
307 if ( p->num != num ) continue;
308 if ((tag == RPMTAG_SOURCE && p->flags == RPMBUILD_ISSOURCE) ||
309 (tag == RPMTAG_PATCH && p->flags == RPMBUILD_ISPATCH)) {
310 rpmlog(RPMLOG_ERR, _("%s %d defined multiple times\n"), name, num);
315 /* Create the entry and link it in */
316 p = xmalloc(sizeof(*p));
318 p->fullSource = xstrdup(field);
320 p->source = strrchr(p->fullSource, '/');
324 p->source = p->fullSource;
327 if (tag != RPMTAG_ICON) {
328 p->next = spec->sources;
337 if (tag != RPMTAG_ICON) {
338 char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
340 rasprintf(&buf, "%s%d",
341 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
342 addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
344 rasprintf(&buf, "%sURL%d",
345 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
346 addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
349 if (!spec->recursing) {
350 rpmlua lua = NULL; /* global state */
351 const char * what = (flag & RPMBUILD_ISPATCH) ? "patches" : "sources";
352 rpmluaPushTable(lua, what);
353 rpmluav var = rpmluavNew();
354 rpmluavSetListMode(var, 1);
355 rpmluavSetValue(var, RPMLUAV_STRING, body);
356 rpmluaSetVar(lua, var);
357 var = rpmluavFree(var);
369 static inline speclines freeSl(speclines sl)
372 if (sl == NULL) return NULL;
373 for (i = 0; i < sl->sl_nlines; i++)
374 sl->sl_lines[i] = _free(sl->sl_lines[i]);
375 sl->sl_lines = _free(sl->sl_lines);
381 static inline spectags freeSt(spectags st)
384 if (st == NULL) return NULL;
385 for (i = 0; i < st->st_ntags; i++) {
386 spectag t = st->st_t + i;
387 t->t_lang = _free(t->t_lang);
388 t->t_msgid = _free(t->t_msgid);
390 st->st_t = _free(st->st_t);
394 rpmSpec newSpec(void)
396 rpmSpec spec = xcalloc(1, sizeof(*spec));
398 spec->specFile = NULL;
403 spec->fileStack = NULL;
404 spec->lbuf[0] = '\0';
405 spec->line = spec->lbuf;
406 spec->nextline = NULL;
407 spec->nextpeekc = '\0';
409 spec->readStack = xcalloc(1, sizeof(*spec->readStack));
410 spec->readStack->next = NULL;
411 spec->readStack->reading = 1;
413 spec->rootDir = NULL;
416 spec->install = NULL;
420 spec->sources = NULL;
421 spec->packages = NULL;
423 spec->numSources = 0;
425 spec->sourceRpmName = NULL;
426 spec->sourcePkgId = NULL;
427 spec->sourceHeader = NULL;
428 spec->sourceCpioList = NULL;
430 spec->buildRoot = NULL;
431 spec->buildSubdir = NULL;
433 spec->passPhrase = NULL;
437 spec->buildRestrictions = headerNew();
438 spec->BANames = NULL;
441 spec->BASpecs = NULL;
446 spec->macros = rpmGlobalMacroContext;
450 /* make sure patches and sources tables always exist */
451 rpmlua lua = NULL; /* global state */
452 rpmluaPushTable(lua, "patches");
453 rpmluaPushTable(lua, "sources");
461 rpmSpec freeSpec(rpmSpec spec)
463 struct ReadLevelEntry *rl;
465 if (spec == NULL) return NULL;
467 spec->sl = freeSl(spec->sl);
468 spec->st = freeSt(spec->st);
470 spec->prep = freeStringBuf(spec->prep);
471 spec->build = freeStringBuf(spec->build);
472 spec->install = freeStringBuf(spec->install);
473 spec->check = freeStringBuf(spec->check);
474 spec->clean = freeStringBuf(spec->clean);
476 spec->buildRoot = _free(spec->buildRoot);
477 spec->buildSubdir = _free(spec->buildSubdir);
478 spec->rootDir = _free(spec->rootDir);
479 spec->specFile = _free(spec->specFile);
483 while (spec->readStack) {
484 rl = spec->readStack;
485 spec->readStack = rl->next;
490 spec->sourceRpmName = _free(spec->sourceRpmName);
491 spec->sourcePkgId = _free(spec->sourcePkgId);
492 spec->sourceHeader = headerFree(spec->sourceHeader);
494 if (spec->sourceCpioList) {
495 rpmfi fi = spec->sourceCpioList;
496 spec->sourceCpioList = NULL;
500 spec->buildRestrictions = headerFree(spec->buildRestrictions);
502 if (!spec->recursing) {
503 if (spec->BASpecs != NULL)
504 while (spec->BACount--) {
505 spec->BASpecs[spec->BACount] =
506 freeSpec(spec->BASpecs[spec->BACount]);
508 spec->BASpecs = _free(spec->BASpecs);
510 spec->BANames = _free(spec->BANames);
512 spec->passPhrase = _free(spec->passPhrase);
513 spec->cookie = _free(spec->cookie);
516 rpmlua lua = NULL; /* global state */
517 rpmluaDelVar(lua, "patches");
518 rpmluaDelVar(lua, "sources");
521 spec->sources = freeSources(spec->sources);
522 spec->packages = freePackages(spec->packages);
529 struct OpenFileInfo * newOpenFileInfo(void)
531 struct OpenFileInfo *ofi;
533 ofi = xmalloc(sizeof(*ofi));
535 ofi->fileName = NULL;
537 ofi->readBuf[0] = '\0';
544 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
548 char * buildRoot = NULL;
550 char * passPhrase = "";
557 if (qva->qva_showPackage == NULL)
560 /* FIX: make spec abstract */
561 if (parseSpec(ts, arg, "/", buildRoot, recursing, passPhrase,
562 cookie, anyarch, force)
563 || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
566 _("query of specfile %s failed, can't parse\n"), arg);
571 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
572 xx = qva->qva_showPackage(qva, ts, pkg->header);
575 spec = freeSpec(spec);