3 * Handle spec data structure.
8 #include "build/buildio.h"
10 #include <rpm/rpmfi.h>
11 #include <rpm/rpmts.h>
12 #include <rpm/rpmlog.h>
13 #include <rpm/rpmfileutil.h>
19 #define SKIPSPACE(s) { while (*(s) && xisspace(*(s))) (s)++; }
20 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
21 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
24 * @param p trigger entry chain
28 struct TriggerFileEntry * freeTriggerFiles(struct TriggerFileEntry * p)
30 struct TriggerFileEntry *o, *q = p;
35 o->fileName = _free(o->fileName);
36 o->script = _free(o->script);
37 o->prog = _free(o->prog);
44 * Destroy source component chain.
45 * @param s source component chain
49 struct Source * freeSources(struct Source * s)
51 struct Source *r, *t = s;
56 r->fullSource = _free(r->fullSource);
62 rpmRC lookupPackage(rpmSpec spec, const char *name, int flag,Package *pkg)
71 *pkg = spec->packages;
75 /* Construct package name */
77 if (flag == PART_SUBNAME) {
78 (void) headerNVR(spec->packages->header, &pname, NULL, NULL);
79 fullName = n = alloca(strlen(pname) + 1 + strlen(name) + 1);
80 while (*pname != '\0') *n++ = *pname++;
83 fullName = n = alloca(strlen(name)+1);
88 /* Locate package with fullName */
89 for (p = spec->packages; p != NULL; p = p->next) {
90 (void) headerNVR(p->header, &pname, NULL, NULL);
91 if (pname && (! strcmp(fullName, pname))) {
98 return ((p == NULL) ? RPMRC_FAIL : RPMRC_OK);
101 Package newPackage(rpmSpec spec)
106 p = xcalloc(1, sizeof(*p));
108 p->header = headerNew();
118 p->triggerScripts = NULL;
121 p->triggerFiles = NULL;
129 p->postInFile = NULL;
131 p->postUnFile = NULL;
132 p->verifyFile = NULL;
134 p->specialDoc = 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 = _constfree(pkg->preInFile);
154 pkg->postInFile = _constfree(pkg->postInFile);
155 pkg->preUnFile = _constfree(pkg->preUnFile);
156 pkg->postUnFile = _constfree(pkg->postUnFile);
157 pkg->verifyFile = _constfree(pkg->verifyFile);
159 pkg->header = headerFree(pkg->header);
160 pkg->ds = rpmdsFree(pkg->ds);
161 pkg->fileList = freeStringBuf(pkg->fileList);
162 pkg->fileFile = _constfree(pkg->fileFile);
164 rpmfi fi = pkg->cpioList;
165 pkg->cpioList = NULL;
169 pkg->specialDoc = freeStringBuf(pkg->specialDoc);
170 pkg->icon = freeSources(pkg->icon);
171 pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
177 Package freePackages(Package packages)
181 while ((p = packages) != NULL) {
191 static inline struct Source *findSource(rpmSpec spec, int num, int flag)
195 for (p = spec->sources; p != NULL; p = p->next)
196 if ((num == p->num) && (p->flags & flag)) return p;
201 int parseNoSource(rpmSpec spec, const char * field, rpm_tag_t 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 (parseNum(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: %d\n"),
234 spec->lineNum, name, num);
238 p->flags |= RPMBUILD_ISNO;
245 int addSource(rpmSpec spec, Package pkg, const char *field, rpm_tag_t tag)
249 const char *name = NULL;
251 const char *fieldp = NULL;
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 ':' */
281 while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t')) {
288 if (nump == NULL || *nump == '\0') {
291 if (parseNum(buf, &num)) {
292 rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
293 spec->lineNum, name, spec->line);
299 /* Create the entry and link it in */
300 p = xmalloc(sizeof(*p));
302 p->fullSource = xstrdup(field);
304 p->source = strrchr(p->fullSource, '/');
308 p->source = p->fullSource;
311 if (tag != RPMTAG_ICON) {
312 p->next = spec->sources;
321 if (tag != RPMTAG_ICON) {
322 char *body = rpmGetPath("%{_sourcedir}/", p->source, NULL);
325 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
326 addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
327 sprintf(buf, "%sURL%d",
328 (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
329 addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
338 static inline speclines newSl(void)
342 sl = xmalloc(sizeof(*sl));
352 static inline speclines freeSl(speclines sl)
355 if (sl == NULL) return NULL;
356 for (i = 0; i < sl->sl_nlines; i++)
357 sl->sl_lines[i] = _free(sl->sl_lines[i]);
358 sl->sl_lines = _free(sl->sl_lines);
364 static inline spectags newSt(void)
368 st = xmalloc(sizeof(*st));
378 static inline spectags freeSt(spectags st)
381 if (st == NULL) return NULL;
382 for (i = 0; i < st->st_ntags; i++) {
383 spectag t = st->st_t + i;
384 t->t_lang = _constfree(t->t_lang);
385 t->t_msgid = _constfree(t->t_msgid);
387 st->st_t = _free(st->st_t);
391 rpmSpec newSpec(void)
393 rpmSpec spec = xcalloc(1, sizeof(*spec));
395 spec->specFile = NULL;
400 spec->fileStack = NULL;
401 spec->lbuf[0] = '\0';
402 spec->line = spec->lbuf;
403 spec->nextline = NULL;
404 spec->nextpeekc = '\0';
406 spec->readStack = xcalloc(1, sizeof(*spec->readStack));
407 spec->readStack->next = NULL;
408 spec->readStack->reading = 1;
410 spec->rootURL = NULL;
413 spec->install = NULL;
417 spec->sources = NULL;
418 spec->packages = NULL;
420 spec->numSources = 0;
422 spec->sourceRpmName = NULL;
423 spec->sourcePkgId = NULL;
424 spec->sourceHeader = NULL;
425 spec->sourceCpioList = NULL;
427 spec->gotBuildRootURL = 0;
428 spec->buildRootURL = NULL;
429 spec->buildSubdir = NULL;
431 spec->passPhrase = NULL;
435 spec->buildRestrictions = headerNew();
436 spec->BANames = NULL;
439 spec->BASpecs = NULL;
444 spec->macros = rpmGlobalMacroContext;
449 rpmSpec freeSpec(rpmSpec spec)
451 struct ReadLevelEntry *rl;
453 if (spec == NULL) return NULL;
455 spec->sl = freeSl(spec->sl);
456 spec->st = freeSt(spec->st);
458 spec->prep = freeStringBuf(spec->prep);
459 spec->build = freeStringBuf(spec->build);
460 spec->install = freeStringBuf(spec->install);
461 spec->check = freeStringBuf(spec->check);
462 spec->clean = freeStringBuf(spec->clean);
464 spec->buildRootURL = _constfree(spec->buildRootURL);
465 spec->buildSubdir = _constfree(spec->buildSubdir);
466 spec->rootURL = _constfree(spec->rootURL);
467 spec->specFile = _constfree(spec->specFile);
470 { struct OpenFileInfo *ofi;
471 while (spec->fileStack) {
472 ofi = spec->fileStack;
473 spec->fileStack = ofi->next;
475 ofi->fileName = _free(ofi->fileName);
483 while (spec->readStack) {
484 rl = spec->readStack;
485 spec->readStack = rl->next;
490 spec->sourceRpmName = _constfree(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 = _constfree(spec->cookie);
515 spec->sources = freeSources(spec->sources);
516 spec->packages = freePackages(spec->packages);
523 struct OpenFileInfo * newOpenFileInfo(void)
525 struct OpenFileInfo *ofi;
527 ofi = xmalloc(sizeof(*ofi));
529 ofi->fileName = NULL;
531 ofi->readBuf[0] = '\0';
539 * Print copy of spec file, filling in Group/Description/Summary from specspo.
540 * @param spec spec file control structure
543 printNewSpecfile(rpmSpec spec)
546 speclines sl = spec->sl;
547 spectags st = spec->st;
548 char * msgstr = NULL;
551 if (sl == NULL || st == NULL)
554 for (i = 0; i < st->st_ntags; i++) {
555 spectag t = st->st_t + i;
556 const char * tn = rpmTagGetName(t->t_tag);
561 if (t->t_msgid == NULL)
562 h = spec->packages->header;
567 strcpy(fmt, t->t_msgid);
568 for (fe = fmt; *fe && *fe != '('; fe++)
570 if (*fe == '(') *fe = '\0';
572 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
575 (void) headerNVR(h, &pkgname, NULL, NULL);
576 if (!strcmp(pkgname, fmt))
579 if (pkg == NULL || h == NULL)
580 h = spec->packages->header;
587 (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
588 msgstr = _free(msgstr);
590 /* XXX this should use queryHeader(), but prints out tn as well. */
591 msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
592 if (msgstr == NULL) {
593 rpmlog(RPMLOG_ERR, _("can't query %s: %s\n"), tn, errstr);
600 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
601 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
603 { char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
604 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
605 sl->sl_lines[t->t_startx] = buf;
608 case RPMTAG_DESCRIPTION:
609 for (j = 1; j < t->t_nlines; j++) {
610 if (*sl->sl_lines[t->t_startx + j] == '%')
612 sl->sl_lines[t->t_startx + j] =
613 _free(sl->sl_lines[t->t_startx + j]);
615 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
616 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
619 sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
621 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
625 msgstr = _free(msgstr);
627 for (i = 0; i < sl->sl_nlines; i++) {
628 const char * s = sl->sl_lines[i];
632 if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
637 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
641 char * buildRoot = NULL;
643 char * passPhrase = "";
650 if (qva->qva_showPackage == NULL)
653 /* FIX: make spec abstract */
654 if (parseSpec(ts, arg, "/", buildRoot, recursing, passPhrase,
655 cookie, anyarch, force)
656 || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
659 _("query of specfile %s failed, can't parse\n"), arg);
665 printNewSpecfile(spec);
669 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next)
670 xx = qva->qva_showPackage(qva, ts, pkg->header);
673 spec = freeSpec(spec);