206 lines
4.6 KiB
C
206 lines
4.6 KiB
C
/* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#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;
|
|
|
|
/* This actually sorts the index, so it'll be easy to catch dups */
|
|
h = headerCopy(inh);
|
|
|
|
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;
|
|
}
|