/* Routine to "verify" a parsed spec file */ /*************** Here's what we do . check for duplicate fields . make sure a certain set of fields are present . in subpackages, make sure a certain set of fields are present . in subpackages, make sure certain fields are *not* present . check for duplicate sources/patch numbers . do some checking on the field values for legit characters ****************/ #include #include #include #include #include "header.h" #include "spec.h" #include "specP.h" #include "messages.h" #include "rpmlib.h" #include "stringbuf.h" #include "misc.h" #define EMPTY(s) ((!(s)) || (!(*(s)))) #define OOPS(s) {fprintf(stderr, "verifySpec: %s\n", s); res = 1;} #define MUST 1 struct packageFieldsRec { int tag; int present; int shouldBePresent; }; struct fieldNamesRec { int tag; char *name; }; static int checkHeaderTags(Header inh, struct packageFieldsRec *pfr); static char *tagName(int tag); /* This is a list of tags related to the "main" package. */ /* Only list those that must or must not be present. */ static struct packageFieldsRec packageFields[] = { { RPMTAG_NAME, 0, MUST }, { RPMTAG_VERSION, 0, MUST }, { RPMTAG_RELEASE, 0, MUST }, /* { RPMTAG_SUMMARY, 0, MUST }, */ { RPMTAG_DESCRIPTION, 0, MUST }, { RPMTAG_COPYRIGHT, 0, MUST }, /* { RPMTAG_PACKAGER, 0, MUST }, */ { RPMTAG_GROUP, 0, MUST }, { 0, 0, 0 }, }; /* This is a list of tags related to "sub" packages. */ /* Only list those that must or must not be present. */ static struct packageFieldsRec subpackageFields[] = { { RPMTAG_NAME, 0, MUST }, /* This is inserted automaticaly */ { RPMTAG_SUMMARY, 0, MUST }, { RPMTAG_DESCRIPTION, 0, MUST }, { RPMTAG_GROUP, 0, MUST }, { RPMTAG_NAME, 0, 0 }, { RPMTAG_COPYRIGHT, 0, 0 }, { RPMTAG_PACKAGER, 0, 0 }, { RPMTAG_BUILDROOT, 0, 0 }, { 0, 0, 0 }, }; static struct packageFieldsRec *findTag(int tag, struct packageFieldsRec *pfr) { struct packageFieldsRec *p = pfr; while (p->tag) { if (p->tag == tag) return p; p++; } return NULL; } static char *tagName(int tag) { int i = 0; static char nameBuf[1024]; char *s; strcpy(nameBuf, "(unknown)"); while (i < rpmTagTableSize) { if (tag == rpmTagTable[i].val) { strcpy(nameBuf, rpmTagTable[i].name + 7); s = nameBuf+1; while (*s) { *s = tolower(*s); s++; } } i++; } return nameBuf; } static int checkHeaderTags(Header inh, struct packageFieldsRec *pfr) { Header h; HeaderIterator headerIter; int res = 0; int_32 tag, lastTag, type, c; void *ptr; struct packageFieldsRec *p; /* Sort the index, so it'll be easy to catch dups */ h = headerCopy(inh); headerSort(h); headerIter = headerInitIterator(h); lastTag = 0; while (headerNextIterator(headerIter, &tag, &type, &ptr, &c)) { if (tag == lastTag) { rpmError(RPMERR_BADSPEC, "Duplicate fields for : %s", tagName(tag)); res = 1; } p = findTag(tag, pfr); if (p) p->present = 1; lastTag = tag; } headerFreeIterator(headerIter); headerFree(h); p = pfr; while (p->tag) { if (p->shouldBePresent != p->present) { rpmError(RPMERR_BADSPEC, "Field must%s be present%s: %s", p->present ? " NOT" : "", p->present ? "" : " ", tagName(p->tag)); res = 1; } p->present = 0; /* hack to clear it for next time :-) */ p++; } return res; } int verifySpec(Spec s) { int res = 0; struct PackageRec *pr; struct packageFieldsRec *fields; char name[1024]; char *val; if (EMPTY(s->name)) { OOPS("No Name field"); } /* Check each package/subpackage */ pr = s->packages; fields = packageFields; while (pr) { if (! pr->subname) { if (pr->newname) { strcpy(name, pr->newname); } else { strcpy(name, s->name); } } else { sprintf(name, "%s-%s", s->name, pr->subname); } printf("* Package: %s\n", name); if (checkHeaderTags(pr->header, fields)) { res = 1; } val = NULL; headerGetEntry(pr->header, RPMTAG_VERSION, NULL, (void *) &val, NULL); if (val && strchr(val, '-')) { rpmError(RPMERR_BADSPEC, "Illegal '-' char in version: %s\n", val); res = 1; } val = NULL; headerGetEntry(pr->header, RPMTAG_RELEASE, NULL, (void *) &val, NULL); if (val && strchr(val, '-')) { rpmError(RPMERR_BADSPEC, "Illegal '-' char in release: %s\n", val); res = 1; } pr = pr->next; fields = subpackageFields; } return res; }