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"
22 #define SKIPSPACE(s) { while (*(s) && risspace(*(s))) (s)++; }
23 #define SKIPWHITE(_x) {while(*(_x) && (risspace(*_x) || *(_x) == ',')) (_x)++;}
24 #define SKIPNONWHITE(_x){while(*(_x) &&!(risspace(*_x) || *(_x) == ',')) (_x)++;}
27 * @param p trigger entry chain
31 struct TriggerFileEntry * freeTriggerFiles(struct TriggerFileEntry * p)
33 struct TriggerFileEntry *o, *q = p;
38 o->fileName = _free(o->fileName);
39 o->script = _free(o->script);
40 o->prog = _free(o->prog);
47 * Destroy source component chain.
48 * @param s source component chain
52 struct Source * freeSources(struct Source * s)
54 struct Source *r, *t = s;
59 r->fullSource = _free(r->fullSource);
65 rpmRC lookupPackage(rpmSpec spec, const char *name, int flag,Package *pkg)
68 char *fullName = NULL;
74 *pkg = spec->packages;
78 /* Construct package name */
79 if (flag == PART_SUBNAME) {
80 (void) headerNVR(spec->packages->header, &pname, NULL, NULL);
81 rasprintf(&fullName, "%s-%s", pname, name);
83 fullName = xstrdup(name);
86 /* Locate package with fullName */
87 for (p = spec->packages; p != NULL; p = p->next) {
88 (void) headerNVR(p->header, &pname, NULL, NULL);
89 if (pname && (! strcmp(fullName, pname))) {
97 return ((p == NULL) ? RPMRC_FAIL : RPMRC_OK);
100 Package newPackage(rpmSpec spec)
105 p = xcalloc(1, sizeof(*p));
107 p->header = headerNew();
117 p->triggerScripts = NULL;
120 p->triggerFiles = NULL;
128 p->postInFile = NULL;
130 p->postUnFile = NULL;
131 p->verifyFile = NULL;
133 p->specialDoc = NULL;
134 p->specialDocDir = NULL;
136 if (spec->packages == NULL) {
139 /* Always add package to end of list */
140 for (pp = spec->packages; pp->next != NULL; pp = pp->next)
149 Package freePackage(Package pkg)
151 if (pkg == NULL) return NULL;
153 pkg->preInFile = _free(pkg->preInFile);
154 pkg->postInFile = _free(pkg->postInFile);
155 pkg->preUnFile = _free(pkg->preUnFile);
156 pkg->postUnFile = _free(pkg->postUnFile);
157 pkg->verifyFile = _free(pkg->verifyFile);
159 pkg->header = headerFree(pkg->header);
160 pkg->ds = rpmdsFree(pkg->ds);
161 pkg->fileList = freeStringBuf(pkg->fileList);
162 pkg->fileFile = _free(pkg->fileFile);
164 rpmfi fi = pkg->cpioList;
165 pkg->cpioList = NULL;
169 pkg->specialDoc = freeStringBuf(pkg->specialDoc);
170 pkg->specialDocDir = _free(pkg->specialDocDir);
171 pkg->icon = freeSources(pkg->icon);
172 pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
178 Package freePackages(Package packages)
182 while ((p = packages) != NULL) {
192 static inline struct Source *findSource(rpmSpec spec, uint32_t num, int flag)
196 for (p = spec->sources; p != NULL; p = p->next)
197 if ((num == p->num) && (p->flags & flag)) return p;
202 int parseNoSource(rpmSpec spec, const char * field, rpmTag tag)
208 if (tag == RPMTAG_NOSOURCE) {
209 flag = RPMBUILD_ISSOURCE;
212 flag = RPMBUILD_ISPATCH;
217 for (f = fe; *f != '\0'; f = fe) {
225 if (*fe != '\0') fe++;
227 if (parseNum(f, &num)) {
228 rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
233 if (! (p = findSource(spec, num, flag))) {
234 rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %d\n"),
235 spec->lineNum, name, num);
239 p->flags |= RPMBUILD_ISNO;
246 int addSource(rpmSpec spec, Package pkg, const char *field, rpmTag tag)
250 const char *name = NULL;
256 switch ((rpm_tag_t) tag) {
258 flag = RPMBUILD_ISSOURCE;
260 fieldp = spec->line + 6;
263 flag = RPMBUILD_ISPATCH;
265 fieldp = spec->line + 5;
268 flag = RPMBUILD_ISICON;
274 if (tag != RPMTAG_ICON) {
275 /* We already know that a ':' exists, and that there */
276 /* are no spaces before it. */
277 /* This also now allows for spaces and tabs between */
278 /* the number and the ':' */
280 char *fieldp_backup = fieldp;
282 while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t')) {
288 nump = fieldp_backup;
290 if (nump == NULL || *nump == '\0') {
293 if (parseNum(fieldp_backup, &num)) {
294 rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
295 spec->lineNum, name, spec->line);
303 /* Create the entry and link it in */
304 p = xmalloc(sizeof(*p));
306 p->fullSource = xstrdup(field);
308 p->source = strrchr(p->fullSource, '/');
312 p->source = p->fullSource;
315 if (tag != RPMTAG_ICON) {
316 p->next = spec->sources;
325 if (tag != RPMTAG_ICON) {
326 char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
328 rasprintf(&buf, "%s%d",
329 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
330 addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
332 rasprintf(&buf, "%sURL%d",
333 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
334 addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
338 rpmlua lua = NULL; /* global state */
339 const char * what = (flag & RPMBUILD_ISPATCH) ? "patches" : "sources";
340 rpmluaPushTable(lua, what);
341 rpmluav var = rpmluavNew();
342 rpmluavSetListMode(var, 1);
343 rpmluavSetValue(var, RPMLUAV_STRING, body);
344 rpmluaSetVar(lua, var);
345 var = rpmluavFree(var);
357 static inline speclines newSl(void)
361 sl = xmalloc(sizeof(*sl));
371 static inline speclines freeSl(speclines sl)
374 if (sl == NULL) return NULL;
375 for (i = 0; i < sl->sl_nlines; i++)
376 sl->sl_lines[i] = _free(sl->sl_lines[i]);
377 sl->sl_lines = _free(sl->sl_lines);
383 static inline spectags newSt(void)
387 st = xmalloc(sizeof(*st));
397 static inline spectags freeSt(spectags st)
400 if (st == NULL) return NULL;
401 for (i = 0; i < st->st_ntags; i++) {
402 spectag t = st->st_t + i;
403 t->t_lang = _free(t->t_lang);
404 t->t_msgid = _free(t->t_msgid);
406 st->st_t = _free(st->st_t);
410 rpmSpec newSpec(void)
412 rpmSpec spec = xcalloc(1, sizeof(*spec));
414 spec->specFile = NULL;
419 spec->fileStack = NULL;
420 spec->lbuf[0] = '\0';
421 spec->line = spec->lbuf;
422 spec->nextline = NULL;
423 spec->nextpeekc = '\0';
425 spec->readStack = xcalloc(1, sizeof(*spec->readStack));
426 spec->readStack->next = NULL;
427 spec->readStack->reading = 1;
429 spec->rootDir = NULL;
432 spec->install = NULL;
436 spec->sources = NULL;
437 spec->packages = NULL;
439 spec->numSources = 0;
441 spec->sourceRpmName = NULL;
442 spec->sourcePkgId = NULL;
443 spec->sourceHeader = NULL;
444 spec->sourceCpioList = NULL;
446 spec->gotBuildRoot = 0;
447 spec->buildRoot = NULL;
448 spec->buildSubdir = NULL;
450 spec->passPhrase = NULL;
454 spec->buildRestrictions = headerNew();
455 spec->BANames = NULL;
458 spec->BASpecs = NULL;
463 spec->macros = rpmGlobalMacroContext;
467 /* make sure patches and sources tables always exist */
468 rpmlua lua = NULL; /* global state */
469 rpmluaPushTable(lua, "patches");
470 rpmluaPushTable(lua, "sources");
478 rpmSpec freeSpec(rpmSpec spec)
480 struct ReadLevelEntry *rl;
482 if (spec == NULL) return NULL;
484 spec->sl = freeSl(spec->sl);
485 spec->st = freeSt(spec->st);
487 spec->prep = freeStringBuf(spec->prep);
488 spec->build = freeStringBuf(spec->build);
489 spec->install = freeStringBuf(spec->install);
490 spec->check = freeStringBuf(spec->check);
491 spec->clean = freeStringBuf(spec->clean);
493 spec->buildRoot = _free(spec->buildRoot);
494 spec->buildSubdir = _free(spec->buildSubdir);
495 spec->rootDir = _free(spec->rootDir);
496 spec->specFile = _free(spec->specFile);
500 while (spec->readStack) {
501 rl = spec->readStack;
502 spec->readStack = rl->next;
507 spec->sourceRpmName = _free(spec->sourceRpmName);
508 spec->sourcePkgId = _free(spec->sourcePkgId);
509 spec->sourceHeader = headerFree(spec->sourceHeader);
511 if (spec->sourceCpioList) {
512 rpmfi fi = spec->sourceCpioList;
513 spec->sourceCpioList = NULL;
517 spec->buildRestrictions = headerFree(spec->buildRestrictions);
519 if (!spec->recursing) {
520 if (spec->BASpecs != NULL)
521 while (spec->BACount--) {
522 spec->BASpecs[spec->BACount] =
523 freeSpec(spec->BASpecs[spec->BACount]);
525 spec->BASpecs = _free(spec->BASpecs);
527 spec->BANames = _free(spec->BANames);
529 spec->passPhrase = _free(spec->passPhrase);
530 spec->cookie = _free(spec->cookie);
533 rpmlua lua = NULL; /* global state */
534 rpmluaDelVar(lua, "patches");
535 rpmluaDelVar(lua, "sources");
538 spec->sources = freeSources(spec->sources);
539 spec->packages = freePackages(spec->packages);
546 struct OpenFileInfo * newOpenFileInfo(void)
548 struct OpenFileInfo *ofi;
550 ofi = xmalloc(sizeof(*ofi));
552 ofi->fileName = NULL;
554 ofi->readBuf[0] = '\0';
562 * Print copy of spec file, filling in Group/Description/Summary from specspo.
563 * @param spec spec file control structure
566 printNewSpecfile(rpmSpec spec)
569 speclines sl = spec->sl;
570 spectags st = spec->st;
571 char * msgstr = NULL;
574 if (sl == NULL || st == NULL)
577 for (i = 0; i < st->st_ntags; i++) {
578 spectag t = st->st_t + i;
579 const char * tn = rpmTagGetName(t->t_tag);
583 if (t->t_msgid == NULL)
584 h = spec->packages->header;
588 char *buf = xstrdup(t->t_msgid);
590 fe = strchr(buf, '(');
592 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
595 (void) headerNVR(h, &pkgname, NULL, NULL);
596 if (!strcmp(pkgname, buf))
599 if (pkg == NULL || h == NULL)
600 h = spec->packages->header;
607 rasprintf(&fmt, "%%{%s}", tn);
608 msgstr = _free(msgstr);
610 msgstr = headerFormat(h, fmt, &errstr);
611 if (msgstr == NULL) {
612 rpmlog(RPMLOG_ERR, _("can't query %s: %s\n"), tn, errstr);
620 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
621 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
624 rasprintf(&buf, "%s: %s", tn, msgstr);
625 sl->sl_lines[t->t_startx] = buf;
628 case RPMTAG_DESCRIPTION:
629 for (j = 1; j < t->t_nlines; j++) {
630 if (*sl->sl_lines[t->t_startx + j] == '%')
632 sl->sl_lines[t->t_startx + j] =
633 _free(sl->sl_lines[t->t_startx + j]);
635 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
636 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
639 sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
641 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
645 msgstr = _free(msgstr);
647 for (i = 0; i < sl->sl_nlines; i++) {
648 const char * s = sl->sl_lines[i];
652 if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
657 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
661 char * buildRoot = NULL;
663 char * passPhrase = "";
670 if (qva->qva_showPackage == NULL)
673 /* FIX: make spec abstract */
674 if (parseSpec(ts, arg, "/", buildRoot, recursing, passPhrase,
675 cookie, anyarch, force)
676 || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
679 _("query of specfile %s failed, can't parse\n"), arg);
685 printNewSpecfile(spec);
689 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
690 xx = qva->qva_showPackage(qva, ts, pkg->header);
693 spec = freeSpec(spec);