00001
00006 #include "system.h"
00007
00008 #include "buildio.h"
00009 #include "rpmds.h"
00010 #include "rpmfi.h"
00011 #include "rpmts.h"
00012
00013 #include "debug.h"
00014
00015
00016 extern int specedit;
00017
00018
00019 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
00020 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
00021
00022
00023
00024
00029 static inline
00030 struct TriggerFileEntry * freeTriggerFiles( struct TriggerFileEntry * p)
00031
00032 {
00033 struct TriggerFileEntry *o, *q = p;
00034
00035 while (q != NULL) {
00036 o = q;
00037 q = q->next;
00038 o->fileName = _free(o->fileName);
00039 o->script = _free(o->script);
00040 o->prog = _free(o->prog);
00041 o = _free(o);
00042 }
00043 return NULL;
00044 }
00045
00051 static inline
00052 struct Source * freeSources( struct Source * s)
00053
00054 {
00055 struct Source *r, *t = s;
00056
00057 while (t != NULL) {
00058 r = t;
00059 t = t->next;
00060 r->fullSource = _free(r->fullSource);
00061 r = _free(r);
00062 }
00063 return NULL;
00064 }
00065
00066
00067 int lookupPackage(Spec spec, const char *name, int flag, Package *pkg)
00068 {
00069 const char *pname;
00070 const char *fullName;
00071 Package p;
00072
00073
00074 if (name == NULL) {
00075 if (pkg)
00076 *pkg = spec->packages;
00077 return 0;
00078 }
00079
00080
00081 { char *n;
00082 if (flag == PART_SUBNAME) {
00083 (void) headerNVR(spec->packages->header, &pname, NULL, NULL);
00084 fullName = n = alloca(strlen(pname) + 1 + strlen(name) + 1);
00085 while (*pname != '\0') *n++ = *pname++;
00086 *n++ = '-';
00087 } else {
00088 fullName = n = alloca(strlen(name)+1);
00089 }
00090
00091 strcpy(n, name);
00092
00093 }
00094
00095
00096 for (p = spec->packages; p != NULL; p = p->next) {
00097 (void) headerNVR(p->header, &pname, NULL, NULL);
00098 if (pname && (! strcmp(fullName, pname))) {
00099 break;
00100 }
00101 }
00102
00103 if (pkg)
00104 *pkg = p;
00105 return ((p == NULL) ? 1 : 0);
00106 }
00107
00108
00109 Package newPackage(Spec spec)
00110 {
00111 Package p;
00112 Package pp;
00113
00114 p = xcalloc(1, sizeof(*p));
00115
00116 p->header = headerNew();
00117 p->ds = NULL;
00118
00119 p->autoProv = 1;
00120 p->autoReq = 1;
00121
00122 #if 0
00123 p->reqProv = NULL;
00124 p->triggers = NULL;
00125 p->triggerScripts = NULL;
00126 #endif
00127
00128 p->triggerFiles = NULL;
00129
00130 p->fileFile = NULL;
00131 p->fileList = NULL;
00132
00133 p->cpioList = NULL;
00134
00135 p->preInFile = NULL;
00136 p->postInFile = NULL;
00137 p->preUnFile = NULL;
00138 p->postUnFile = NULL;
00139 p->verifyFile = NULL;
00140
00141 p->specialDoc = NULL;
00142
00143 if (spec->packages == NULL) {
00144 spec->packages = p;
00145 } else {
00146
00147 for (pp = spec->packages; pp->next != NULL; pp = pp->next)
00148 {};
00149 pp->next = p;
00150 }
00151 p->next = NULL;
00152
00153 return p;
00154 }
00155
00156 Package freePackage(Package pkg)
00157 {
00158 if (pkg == NULL) return NULL;
00159
00160 pkg->preInFile = _free(pkg->preInFile);
00161 pkg->postInFile = _free(pkg->postInFile);
00162 pkg->preUnFile = _free(pkg->preUnFile);
00163 pkg->postUnFile = _free(pkg->postUnFile);
00164 pkg->verifyFile = _free(pkg->verifyFile);
00165
00166 pkg->header = headerFree(pkg->header);
00167 pkg->ds = rpmdsFree(pkg->ds);
00168 pkg->fileList = freeStringBuf(pkg->fileList);
00169 pkg->fileFile = _free(pkg->fileFile);
00170 if (pkg->cpioList) {
00171 rpmfi fi = pkg->cpioList;
00172 pkg->cpioList = NULL;
00173 fi = rpmfiFree(fi);
00174 }
00175
00176 pkg->specialDoc = freeStringBuf(pkg->specialDoc);
00177 pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
00178
00179 pkg = _free(pkg);
00180 return NULL;
00181 }
00182
00183 Package freePackages(Package packages)
00184 {
00185 Package p;
00186
00187 while ((p = packages) != NULL) {
00188 packages = p->next;
00189 p->next = NULL;
00190 p = freePackage(p);
00191 }
00192 return NULL;
00193 }
00194
00197 static inline struct Source *findSource(Spec spec, int num, int flag)
00198
00199 {
00200 struct Source *p;
00201
00202 for (p = spec->sources; p != NULL; p = p->next)
00203 if ((num == p->num) && (p->flags & flag)) return p;
00204
00205 return NULL;
00206 }
00207
00208
00209 int parseNoSource(Spec spec, const char * field, int tag)
00210 {
00211 const char *f, *fe;
00212 const char *name;
00213 int num, flag;
00214
00215 if (tag == RPMTAG_NOSOURCE) {
00216 flag = RPMFILE_SOURCE;
00217 name = "source";
00218 } else {
00219 flag = RPMFILE_PATCH;
00220 name = "patch";
00221 }
00222
00223 fe = field;
00224 for (f = fe; *f != '\0'; f = fe) {
00225 struct Source *p;
00226
00227 SKIPWHITE(f);
00228 if (*f == '\0')
00229 break;
00230 fe = f;
00231 SKIPNONWHITE(fe);
00232 if (*fe != '\0') fe++;
00233
00234 if (parseNum(f, &num)) {
00235 rpmError(RPMERR_BADSPEC, _("line %d: Bad number: %s\n"),
00236 spec->lineNum, f);
00237 return RPMERR_BADSPEC;
00238 }
00239
00240 if (! (p = findSource(spec, num, flag))) {
00241 rpmError(RPMERR_BADSPEC, _("line %d: Bad no%s number: %d\n"),
00242 spec->lineNum, name, num);
00243 return RPMERR_BADSPEC;
00244 }
00245
00246 p->flags |= RPMFILE_GHOST;
00247
00248 }
00249
00250 return 0;
00251 }
00252
00253
00254
00255 int addSource(Spec spec, Package pkg, const char *field, int tag)
00256 {
00257 struct Source *p;
00258 int flag = 0;
00259 const char *name = NULL;
00260 const char *mdir = NULL;
00261 char *nump;
00262 const char *fieldp = NULL;
00263 char buf[BUFSIZ];
00264 int num = 0;
00265
00266 buf[0] = '\0';
00267
00268 switch (tag) {
00269 case RPMTAG_SOURCE:
00270 flag = RPMFILE_SOURCE;
00271 name = "source";
00272 mdir = "%{_sourcedir}/";
00273 fieldp = spec->line + (sizeof("Source")-1);
00274 break;
00275 case RPMTAG_PATCH:
00276 flag = RPMFILE_PATCH;
00277 name = "patch";
00278 mdir = "%{_patchdir}/";
00279 fieldp = spec->line + (sizeof("Patch")-1);
00280 break;
00281 case RPMTAG_ICON:
00282 flag = RPMFILE_ICON;
00283 name = "icon";
00284 mdir = "%{_icondir}/";
00285 fieldp = NULL;
00286 break;
00287 default:
00288 assert(0);
00289 break;
00290 }
00291
00292
00293
00294 if (fieldp != NULL) {
00295
00296
00297
00298
00299
00300 nump = buf;
00301 while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t'))
00302 *nump++ = *fieldp++;
00303 *nump = '\0';
00304
00305 nump = buf;
00306 SKIPSPACE(nump);
00307 if (nump == NULL || *nump == '\0')
00308 num = 0;
00309 else if (parseNum(buf, &num)) {
00310 rpmError(RPMERR_BADSPEC, _("line %d: Bad %s number: %s\n"),
00311 spec->lineNum, name, spec->line);
00312 return RPMERR_BADSPEC;
00313 }
00314 }
00315
00316
00317 p = xmalloc(sizeof(*p));
00318 p->num = num;
00319 p->fullSource = xstrdup(field);
00320 p->flags = flag;
00321 p->source = strrchr(p->fullSource, '/');
00322 if (p->source)
00323 p->source++;
00324 else
00325 p->source = p->fullSource;
00326
00327 p->next = spec->sources;
00328 spec->sources = p;
00329
00330 spec->numSources++;
00331
00332
00333 if (tag != RPMTAG_ICON) {
00334 const char *body = rpmGenPath(NULL, mdir, p->source);
00335
00336 sprintf(buf, "%s%d",
00337 (flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
00338 addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
00339 sprintf(buf, "%sURL%d",
00340 (flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
00341 addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
00342 body = _free(body);
00343 }
00344
00345 return 0;
00346 }
00347
00348
00351 static inline speclines newSl(void)
00352
00353 {
00354 speclines sl = NULL;
00355
00356 if (specedit) {
00357 sl = xmalloc(sizeof(*sl));
00358 sl->sl_lines = NULL;
00359 sl->sl_nalloc = 0;
00360 sl->sl_nlines = 0;
00361 }
00362
00363 return sl;
00364 }
00365
00368
00369 static inline speclines freeSl( speclines sl)
00370
00371 {
00372 int i;
00373 if (sl == NULL) return NULL;
00374 for (i = 0; i < sl->sl_nlines; i++)
00375
00376 sl->sl_lines[i] = _free(sl->sl_lines[i]);
00377
00378 sl->sl_lines = _free(sl->sl_lines);
00379 return _free(sl);
00380 }
00381
00382
00385 static inline spectags newSt(void)
00386
00387 {
00388 spectags st = NULL;
00389
00390 if (specedit) {
00391 st = xmalloc(sizeof(*st));
00392 st->st_t = NULL;
00393 st->st_nalloc = 0;
00394 st->st_ntags = 0;
00395 }
00396
00397 return st;
00398 }
00399
00402 static inline spectags freeSt( spectags st)
00403
00404 {
00405 int i;
00406 if (st == NULL) return NULL;
00407 for (i = 0; i < st->st_ntags; i++) {
00408 spectag t = st->st_t + i;
00409 t->t_lang = _free(t->t_lang);
00410 t->t_msgid = _free(t->t_msgid);
00411 }
00412 st->st_t = _free(st->st_t);
00413 return _free(st);
00414 }
00415
00416 Spec newSpec(void)
00417 {
00418 Spec spec = xcalloc(1, sizeof(*spec));
00419
00420 spec->specFile = NULL;
00421
00422 spec->sl = newSl();
00423 spec->st = newSt();
00424
00425 spec->fileStack = NULL;
00426
00427 spec->lbuf[0] = '\0';
00428
00429 spec->line = spec->lbuf;
00430 spec->nextline = NULL;
00431 spec->nextpeekc = '\0';
00432 spec->lineNum = 0;
00433 spec->readStack = xcalloc(1, sizeof(*spec->readStack));
00434 spec->readStack->next = NULL;
00435 spec->readStack->reading = 1;
00436
00437 spec->rootURL = NULL;
00438 spec->prep = NULL;
00439 spec->build = NULL;
00440 spec->install = NULL;
00441 spec->check = NULL;
00442 spec->clean = NULL;
00443
00444 spec->sources = NULL;
00445 spec->packages = NULL;
00446 spec->noSource = 0;
00447 spec->numSources = 0;
00448
00449 spec->sourceRpmName = NULL;
00450 spec->sourcePkgId = NULL;
00451 spec->sourceHeader = headerNew();
00452 spec->sourceCpioList = NULL;
00453
00454 spec->buildSubdir = NULL;
00455
00456 spec->passPhrase = NULL;
00457 spec->timeCheck = 0;
00458 spec->cookie = NULL;
00459
00460 spec->BANames = NULL;
00461 spec->BACount = 0;
00462 spec->recursing = 0;
00463 spec->BASpecs = NULL;
00464
00465 spec->force = 0;
00466 spec->anyarch = 0;
00467
00468 spec->macros = rpmGlobalMacroContext;
00469
00470 spec->_parseRCPOT = parseRCPOT;
00471
00472 return spec;
00473 }
00474
00475 Spec freeSpec(Spec spec)
00476 {
00477 struct ReadLevelEntry *rl;
00478
00479 if (spec == NULL) return NULL;
00480
00481 spec->sl = freeSl(spec->sl);
00482 spec->st = freeSt(spec->st);
00483
00484 spec->prep = freeStringBuf(spec->prep);
00485 spec->build = freeStringBuf(spec->build);
00486 spec->install = freeStringBuf(spec->install);
00487 spec->check = freeStringBuf(spec->check);
00488 spec->clean = freeStringBuf(spec->clean);
00489
00490 spec->buildSubdir = _free(spec->buildSubdir);
00491 spec->rootURL = _free(spec->rootURL);
00492 spec->specFile = _free(spec->specFile);
00493
00494 #ifdef DEAD
00495 { struct OpenFileInfo *ofi;
00496 while (spec->fileStack) {
00497 ofi = spec->fileStack;
00498 spec->fileStack = ofi->next;
00499 ofi->next = NULL;
00500 ofi->fileName = _free(ofi->fileName);
00501 ofi = _free(ofi);
00502 }
00503 }
00504 #else
00505 closeSpec(spec);
00506 #endif
00507
00508 while (spec->readStack) {
00509 rl = spec->readStack;
00510
00511 spec->readStack = rl->next;
00512
00513 rl->next = NULL;
00514 rl = _free(rl);
00515 }
00516
00517 spec->sourceRpmName = _free(spec->sourceRpmName);
00518 spec->sourcePkgId = _free(spec->sourcePkgId);
00519 spec->sourceHeader = headerFree(spec->sourceHeader);
00520
00521 if (spec->sourceCpioList) {
00522 rpmfi fi = spec->sourceCpioList;
00523 spec->sourceCpioList = NULL;
00524 fi = rpmfiFree(fi);
00525 }
00526
00527 if (!spec->recursing) {
00528
00529 if (spec->BASpecs != NULL)
00530 while (spec->BACount--) {
00531
00532 spec->BASpecs[spec->BACount] =
00533 freeSpec(spec->BASpecs[spec->BACount]);
00534
00535 }
00536
00537
00538 spec->BASpecs = _free(spec->BASpecs);
00539
00540 }
00541 spec->BANames = _free(spec->BANames);
00542
00543 spec->passPhrase = _free(spec->passPhrase);
00544 spec->cookie = _free(spec->cookie);
00545
00546 spec->sources = freeSources(spec->sources);
00547 spec->packages = freePackages(spec->packages);
00548
00549 spec = _free(spec);
00550
00551 return spec;
00552 }
00553
00554
00555 struct OpenFileInfo * newOpenFileInfo(void)
00556 {
00557 struct OpenFileInfo *ofi;
00558
00559 ofi = xmalloc(sizeof(*ofi));
00560 ofi->fd = NULL;
00561 ofi->fileName = NULL;
00562 ofi->lineNum = 0;
00563
00564 ofi->readBuf[0] = '\0';
00565
00566 ofi->readPtr = NULL;
00567 ofi->next = NULL;
00568
00569 return ofi;
00570 }
00571
00576 static void
00577 printNewSpecfile(Spec spec)
00578
00579
00580 {
00581 Header h;
00582 speclines sl = spec->sl;
00583 spectags st = spec->st;
00584 const char * msgstr = NULL;
00585 int i, j;
00586
00587 if (sl == NULL || st == NULL)
00588 return;
00589
00590
00591 for (i = 0; i < st->st_ntags; i++) {
00592 spectag t = st->st_t + i;
00593 const char * tn = tagName(t->t_tag);
00594 const char * errstr;
00595 char fmt[1024];
00596
00597 fmt[0] = '\0';
00598 if (t->t_msgid == NULL)
00599 h = spec->packages->header;
00600 else {
00601 Package pkg;
00602 char *fe;
00603
00604
00605 strcpy(fmt, t->t_msgid);
00606 for (fe = fmt; *fe && *fe != '('; fe++)
00607 {} ;
00608 if (*fe == '(') *fe = '\0';
00609
00610 h = NULL;
00611 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00612 const char *pkgname;
00613 h = pkg->header;
00614 (void) headerNVR(h, &pkgname, NULL, NULL);
00615 if (!strcmp(pkgname, fmt))
00616 break;
00617 }
00618 if (pkg == NULL || h == NULL)
00619 h = spec->packages->header;
00620 }
00621
00622 if (h == NULL)
00623 continue;
00624
00625 fmt[0] = '\0';
00626
00627 (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
00628
00629 msgstr = _free(msgstr);
00630
00631
00632 msgstr = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
00633 if (msgstr == NULL) {
00634 rpmError(RPMERR_QFMT, _("can't query %s: %s\n"), tn, errstr);
00635 return;
00636 }
00637
00638
00639 switch(t->t_tag) {
00640 case RPMTAG_SUMMARY:
00641 case RPMTAG_GROUP:
00642
00643 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00644
00645 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
00646 continue;
00647 { char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
00648 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
00649 sl->sl_lines[t->t_startx] = buf;
00650 }
00651 break;
00652 case RPMTAG_DESCRIPTION:
00653 for (j = 1; j < t->t_nlines; j++) {
00654 if (*sl->sl_lines[t->t_startx + j] == '%')
00655 continue;
00656
00657 sl->sl_lines[t->t_startx + j] =
00658 _free(sl->sl_lines[t->t_startx + j]);
00659
00660 }
00661 if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
00662 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00663 continue;
00664 }
00665 sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
00666 if (t->t_nlines > 2)
00667 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
00668 break;
00669 }
00670
00671 }
00672
00673 msgstr = _free(msgstr);
00674
00675
00676 for (i = 0; i < sl->sl_nlines; i++) {
00677 const char * s = sl->sl_lines[i];
00678 if (s == NULL)
00679 continue;
00680 printf("%s", s);
00681 if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
00682 printf("\n");
00683 }
00684
00685 }
00686
00695 static int _specQuery(rpmts ts, QVA_t qva, const char *specName,
00696 const char *target)
00697
00698
00699 {
00700 Spec spec = NULL;
00701 Package pkg;
00702 int res = 1;
00703 int anyarch = (target == NULL) ? 1 : 0;
00704 char * passPhrase = "";
00705 int recursing = 0;
00706 char *cookie = NULL;
00707 int force = 1;
00708 int verify = 0;
00709 int xx;
00710
00711
00712
00713 if (parseSpec(ts, specName, "/", recursing, passPhrase,
00714 cookie, anyarch, force, verify)
00715 || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
00716 {
00717 rpmError(RPMERR_QUERY,
00718 _("query of specfile %s failed, can't parse\n"),
00719 specName);
00720 goto exit;
00721 }
00722
00723
00724
00725 res = 0;
00726 if (specedit) {
00727 printNewSpecfile(spec);
00728 goto exit;
00729 }
00730
00731 switch (qva->qva_source) {
00732 case RPMQV_SPECSRPM:
00733 xx = initSourceHeader(spec, NULL);
00734 xx = qva->qva_showPackage(qva, ts, spec->sourceHeader);
00735 break;
00736 default:
00737 case RPMQV_SPECFILE:
00738 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00739
00740
00741
00742
00743 if (target == NULL || pkg->fileList != NULL)
00744 xx = qva->qva_showPackage(qva, ts, pkg->header);
00745 }
00746 break;
00747 }
00748
00749 exit:
00750 spec = freeSpec(spec);
00751 return res;
00752 }
00753
00754 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
00755 {
00756 int res = 1;
00757 const char * targets = rpmcliTargets;
00758 char *target;
00759 const char * t;
00760 const char * te;
00761 const char * rcfile = rpmcliRcfile;
00762 int nqueries = 0;
00763
00764 if (qva->qva_showPackage == NULL)
00765 goto exit;
00766
00767 if (targets == NULL) {
00768 res = _specQuery(ts, qva, arg, NULL);
00769 nqueries++;
00770 goto exit;
00771 }
00772
00773 rpmMessage(RPMMESS_DEBUG,
00774 _("Query specfile for platform(s): %s\n"), targets);
00775 for (t = targets; *t != '\0'; t = te) {
00776
00777 if ((te = strchr(t, ',')) == NULL)
00778 te = t + strlen(t);
00779 target = alloca(te-t+1);
00780 strncpy(target, t, (te-t));
00781 target[te-t] = '\0';
00782 if (*te != '\0')
00783 te++;
00784
00785
00786 rpmMessage(RPMMESS_DEBUG, _(" target platform: %s\n"), target);
00787
00788 if (t != targets) {
00789 rpmFreeMacros(NULL);
00790 rpmFreeRpmrc();
00791 (void) rpmReadConfigFiles(rcfile, target);
00792 }
00793 res = _specQuery(ts, qva, arg, target);
00794 nqueries++;
00795 if (res) break;
00796 }
00797
00798 exit:
00799
00800 if (nqueries > 1) {
00801 t = targets;
00802 if ((te = strchr(t, ',')) == NULL)
00803 te = t + strlen(t);
00804 target = alloca(te-t+1);
00805 strncpy(target, t, (te-t));
00806 target[te-t] = '\0';
00807 if (*te != '\0')
00808 te++;
00809 rpmFreeMacros(NULL);
00810 rpmFreeRpmrc();
00811 (void) rpmReadConfigFiles(rcfile, target);
00812 }
00813 return res;
00814 }