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)
74 *pkg = spec->packages;
78 /* Construct package name */
80 if (flag == PART_SUBNAME) {
81 (void) headerNVR(spec->packages->header, &pname, NULL, NULL);
82 fullName = n = alloca(strlen(pname) + 1 + strlen(name) + 1);
83 while (*pname != '\0') *n++ = *pname++;
86 fullName = n = alloca(strlen(name)+1);
91 /* Locate package with fullName */
92 for (p = spec->packages; p != NULL; p = p->next) {
93 (void) headerNVR(p->header, &pname, NULL, NULL);
94 if (pname && (! strcmp(fullName, pname))) {
101 return ((p == NULL) ? RPMRC_FAIL : RPMRC_OK);
104 Package newPackage(rpmSpec spec)
109 p = xcalloc(1, sizeof(*p));
111 p->header = headerNew();
121 p->triggerScripts = NULL;
124 p->triggerFiles = NULL;
132 p->postInFile = NULL;
134 p->postUnFile = NULL;
135 p->verifyFile = NULL;
137 p->specialDoc = NULL;
139 if (spec->packages == NULL) {
142 /* Always add package to end of list */
143 for (pp = spec->packages; pp->next != NULL; pp = pp->next)
152 Package freePackage(Package pkg)
154 if (pkg == NULL) return NULL;
156 pkg->preInFile = _free(pkg->preInFile);
157 pkg->postInFile = _free(pkg->postInFile);
158 pkg->preUnFile = _free(pkg->preUnFile);
159 pkg->postUnFile = _free(pkg->postUnFile);
160 pkg->verifyFile = _free(pkg->verifyFile);
162 pkg->header = headerFree(pkg->header);
163 pkg->ds = rpmdsFree(pkg->ds);
164 pkg->fileList = freeStringBuf(pkg->fileList);
165 pkg->fileFile = _free(pkg->fileFile);
167 rpmfi fi = pkg->cpioList;
168 pkg->cpioList = NULL;
172 pkg->specialDoc = freeStringBuf(pkg->specialDoc);
173 pkg->icon = freeSources(pkg->icon);
174 pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
180 Package freePackages(Package packages)
184 while ((p = packages) != NULL) {
194 static inline struct Source *findSource(rpmSpec spec, int num, int flag)
198 for (p = spec->sources; p != NULL; p = p->next)
199 if ((num == p->num) && (p->flags & flag)) return p;
204 int parseNoSource(rpmSpec spec, const char * field, rpmTag tag)
210 if (tag == RPMTAG_NOSOURCE) {
211 flag = RPMBUILD_ISSOURCE;
214 flag = RPMBUILD_ISPATCH;
219 for (f = fe; *f != '\0'; f = fe) {
227 if (*fe != '\0') fe++;
229 if (parseNum(f, &num)) {
230 rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
235 if (! (p = findSource(spec, num, flag))) {
236 rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %d\n"),
237 spec->lineNum, name, num);
241 p->flags |= RPMBUILD_ISNO;
248 int addSource(rpmSpec spec, Package pkg, const char *field, rpmTag tag)
252 const char *name = NULL;
258 switch ((rpm_tag_t) tag) {
260 flag = RPMBUILD_ISSOURCE;
262 fieldp = spec->line + 6;
265 flag = RPMBUILD_ISPATCH;
267 fieldp = spec->line + 5;
270 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') {
295 if (parseNum(fieldp_backup, &num)) {
296 rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
297 spec->lineNum, name, spec->line);
305 /* Create the entry and link it in */
306 p = xmalloc(sizeof(*p));
308 p->fullSource = xstrdup(field);
310 p->source = strrchr(p->fullSource, '/');
314 p->source = p->fullSource;
317 if (tag != RPMTAG_ICON) {
318 p->next = spec->sources;
327 if (tag != RPMTAG_ICON) {
328 char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
330 rasprintf(&buf, "%s%d",
331 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
332 addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
334 rasprintf(&buf, "%sURL%d",
335 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
336 addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
340 rpmlua lua = NULL; /* global state */
341 const char * what = (flag & RPMBUILD_ISPATCH) ? "patches" : "sources";
342 rpmluaPushTable(lua, what);
343 rpmluav var = rpmluavNew();
344 rpmluavSetListMode(var, 1);
345 rpmluavSetValue(var, RPMLUAV_STRING, body);
346 rpmluaSetVar(lua, var);
347 var = rpmluavFree(var);
359 static inline speclines newSl(void)
363 sl = xmalloc(sizeof(*sl));
373 static inline speclines freeSl(speclines sl)
376 if (sl == NULL) return NULL;
377 for (i = 0; i < sl->sl_nlines; i++)
378 sl->sl_lines[i] = _free(sl->sl_lines[i]);
379 sl->sl_lines = _free(sl->sl_lines);
385 static inline spectags newSt(void)
389 st = xmalloc(sizeof(*st));
399 static inline spectags freeSt(spectags st)
402 if (st == NULL) return NULL;
403 for (i = 0; i < st->st_ntags; i++) {
404 spectag t = st->st_t + i;
405 t->t_lang = _free(t->t_lang);
406 t->t_msgid = _free(t->t_msgid);
408 st->st_t = _free(st->st_t);
412 rpmSpec newSpec(void)
414 rpmSpec spec = xcalloc(1, sizeof(*spec));
416 spec->specFile = NULL;
421 spec->fileStack = NULL;
422 spec->lbuf[0] = '\0';
423 spec->line = spec->lbuf;
424 spec->nextline = NULL;
425 spec->nextpeekc = '\0';
427 spec->readStack = xcalloc(1, sizeof(*spec->readStack));
428 spec->readStack->next = NULL;
429 spec->readStack->reading = 1;
431 spec->rootURL = NULL;
434 spec->install = NULL;
438 spec->sources = NULL;
439 spec->packages = NULL;
441 spec->numSources = 0;
443 spec->sourceRpmName = NULL;
444 spec->sourcePkgId = NULL;
445 spec->sourceHeader = NULL;
446 spec->sourceCpioList = NULL;
448 spec->gotBuildRootURL = 0;
449 spec->buildRootURL = NULL;
450 spec->buildSubdir = NULL;
452 spec->passPhrase = NULL;
456 spec->buildRestrictions = headerNew();
457 spec->BANames = NULL;
460 spec->BASpecs = NULL;
465 spec->macros = rpmGlobalMacroContext;
469 /* make sure patches and sources tables always exist */
470 rpmlua lua = NULL; /* global state */
471 rpmluaPushTable(lua, "patches");
472 rpmluaPushTable(lua, "sources");
480 rpmSpec freeSpec(rpmSpec spec)
482 struct ReadLevelEntry *rl;
484 if (spec == NULL) return NULL;
486 spec->sl = freeSl(spec->sl);
487 spec->st = freeSt(spec->st);
489 spec->prep = freeStringBuf(spec->prep);
490 spec->build = freeStringBuf(spec->build);
491 spec->install = freeStringBuf(spec->install);
492 spec->check = freeStringBuf(spec->check);
493 spec->clean = freeStringBuf(spec->clean);
495 spec->buildRootURL = _free(spec->buildRootURL);
496 spec->buildSubdir = _free(spec->buildSubdir);
497 spec->rootURL = _free(spec->rootURL);
498 spec->specFile = _free(spec->specFile);
502 while (spec->readStack) {
503 rl = spec->readStack;
504 spec->readStack = rl->next;
509 spec->sourceRpmName = _free(spec->sourceRpmName);
510 spec->sourcePkgId = _free(spec->sourcePkgId);
511 spec->sourceHeader = headerFree(spec->sourceHeader);
513 if (spec->sourceCpioList) {
514 rpmfi fi = spec->sourceCpioList;
515 spec->sourceCpioList = NULL;
519 spec->buildRestrictions = headerFree(spec->buildRestrictions);
521 if (!spec->recursing) {
522 if (spec->BASpecs != NULL)
523 while (spec->BACount--) {
524 spec->BASpecs[spec->BACount] =
525 freeSpec(spec->BASpecs[spec->BACount]);
527 spec->BASpecs = _free(spec->BASpecs);
529 spec->BANames = _free(spec->BANames);
531 spec->passPhrase = _free(spec->passPhrase);
532 spec->cookie = _free(spec->cookie);
535 rpmlua lua = NULL; /* global state */
536 rpmluaDelVar(lua, "patches");
537 rpmluaDelVar(lua, "sources");
540 spec->sources = freeSources(spec->sources);
541 spec->packages = freePackages(spec->packages);
548 struct OpenFileInfo * newOpenFileInfo(void)
550 struct OpenFileInfo *ofi;
552 ofi = xmalloc(sizeof(*ofi));
554 ofi->fileName = NULL;
556 ofi->readBuf[0] = '\0';
564 * Print copy of spec file, filling in Group/Description/Summary from specspo.
565 * @param spec spec file control structure
568 printNewSpecfile(rpmSpec spec)
571 speclines sl = spec->sl;
572 spectags st = spec->st;
573 char * msgstr = NULL;
576 if (sl == NULL || st == NULL)
579 for (i = 0; i < st->st_ntags; i++) {
580 spectag t = st->st_t + i;
581 const char * tn = rpmTagGetName(t->t_tag);
586 if (t->t_msgid == NULL)
587 h = spec->packages->header;
592 strcpy(fmt, t->t_msgid);
593 for (fe = fmt; *fe && *fe != '('; fe++)
595 if (*fe == '(') *fe = '\0';
597 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
600 (void) headerNVR(h, &pkgname, NULL, NULL);
601 if (!strcmp(pkgname, fmt))
604 if (pkg == NULL || h == NULL)
605 h = spec->packages->header;
612 (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
613 msgstr = _free(msgstr);
615 /* XXX this should use queryHeader(), but prints out tn as well. */
616 msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
617 if (msgstr == NULL) {
618 rpmlog(RPMLOG_ERR, _("can't query %s: %s\n"), tn, errstr);
625 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
626 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
628 { char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
629 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
630 sl->sl_lines[t->t_startx] = buf;
633 case RPMTAG_DESCRIPTION:
634 for (j = 1; j < t->t_nlines; j++) {
635 if (*sl->sl_lines[t->t_startx + j] == '%')
637 sl->sl_lines[t->t_startx + j] =
638 _free(sl->sl_lines[t->t_startx + j]);
640 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
641 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
644 sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
646 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
650 msgstr = _free(msgstr);
652 for (i = 0; i < sl->sl_nlines; i++) {
653 const char * s = sl->sl_lines[i];
657 if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
662 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
666 char * buildRoot = NULL;
668 char * passPhrase = "";
675 if (qva->qva_showPackage == NULL)
678 /* FIX: make spec abstract */
679 if (parseSpec(ts, arg, "/", buildRoot, recursing, passPhrase,
680 cookie, anyarch, force)
681 || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
684 _("query of specfile %s failed, can't parse\n"), arg);
690 printNewSpecfile(spec);
694 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
695 xx = qva->qva_showPackage(qva, ts, pkg->header);
698 spec = freeSpec(spec);