1995-11-28 06:31:21 +08:00
|
|
|
/* RPM - Copyright (C) 1995 Red Hat Software
|
|
|
|
*
|
|
|
|
* spec.c - routines for parsing a spec file
|
|
|
|
*/
|
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
/*****************************
|
|
|
|
TODO:
|
|
|
|
|
1996-01-08 15:03:21 +08:00
|
|
|
. should be able to drop the -n in non-%package parts
|
1995-12-13 01:53:17 +08:00
|
|
|
|
|
|
|
******************************/
|
|
|
|
|
1997-05-07 22:56:06 +08:00
|
|
|
#include "config.h"
|
1997-05-20 23:57:39 +08:00
|
|
|
#include "miscfn.h"
|
1997-05-07 22:56:06 +08:00
|
|
|
|
|
|
|
#if HAVE_ALLOCA_H
|
|
|
|
# include <alloca.h>
|
|
|
|
#endif
|
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
1996-12-12 11:34:18 +08:00
|
|
|
#include <sys/types.h>
|
1997-04-29 04:45:05 +08:00
|
|
|
#include <time.h>
|
1997-01-25 12:48:06 +08:00
|
|
|
#include <sys/time.h>
|
1995-12-28 00:50:50 +08:00
|
|
|
#include <limits.h>
|
1996-05-08 02:49:33 +08:00
|
|
|
#include <ctype.h>
|
1995-12-13 01:53:17 +08:00
|
|
|
|
1995-11-28 06:31:21 +08:00
|
|
|
#include "header.h"
|
|
|
|
#include "spec.h"
|
1995-12-14 23:52:51 +08:00
|
|
|
#include "specP.h"
|
1995-12-12 06:52:59 +08:00
|
|
|
#include "messages.h"
|
1995-12-13 01:53:17 +08:00
|
|
|
#include "rpmlib.h"
|
1995-12-13 23:57:59 +08:00
|
|
|
#include "stringbuf.h"
|
1995-12-28 00:50:50 +08:00
|
|
|
#include "misc.h"
|
1996-06-08 02:31:08 +08:00
|
|
|
#include "reqprov.h"
|
1996-11-15 01:36:01 +08:00
|
|
|
#include "trigger.h"
|
1997-03-31 22:16:11 +08:00
|
|
|
#include "macro.h"
|
1995-11-28 06:31:21 +08:00
|
|
|
|
|
|
|
#define LINE_BUF_SIZE 1024
|
1995-12-13 01:53:17 +08:00
|
|
|
#define FREE(x) { if (x) free(x); }
|
1995-11-28 06:31:21 +08:00
|
|
|
|
1995-12-13 23:57:59 +08:00
|
|
|
static struct PackageRec *new_packagerec(void);
|
1995-12-12 06:52:59 +08:00
|
|
|
static int read_line(FILE *f, char *line);
|
|
|
|
static int match_arch(char *s);
|
|
|
|
static int match_os(char *s);
|
|
|
|
static void free_packagerec(struct PackageRec *p);
|
1997-04-15 04:05:43 +08:00
|
|
|
static void generateNames(Spec s);
|
1995-12-13 01:53:17 +08:00
|
|
|
static void reset_spec(void);
|
|
|
|
static int find_preamble_line(char *line, char **s);
|
|
|
|
static int check_part(char *line, char **s);
|
1996-02-23 10:22:18 +08:00
|
|
|
static int lookup_package(Spec s, struct PackageRec **pr,
|
|
|
|
char *name, int flags);
|
1995-12-14 23:52:51 +08:00
|
|
|
static void dumpPackage(struct PackageRec *p, FILE *f);
|
|
|
|
|
1997-01-25 12:48:06 +08:00
|
|
|
static int dateToTimet(const char * datestr, time_t * secs);
|
|
|
|
static void addChangelogEntry(Header h, int time, char *name, char *text);
|
|
|
|
static int addChangelog(Header h, StringBuf sb);
|
1996-06-08 02:31:08 +08:00
|
|
|
|
1996-05-08 02:49:33 +08:00
|
|
|
static int parseProvides(struct PackageRec *p, char *line);
|
1996-06-28 04:15:53 +08:00
|
|
|
static int parseRequiresConflicts(struct PackageRec *p, char *line,
|
|
|
|
int flag);
|
1996-06-08 02:31:08 +08:00
|
|
|
static void free_reqprov(struct ReqProv *p);
|
1996-06-28 01:22:18 +08:00
|
|
|
static int noSourcePatch(Spec s, char *line, int_32 tag);
|
1996-05-08 02:49:33 +08:00
|
|
|
|
1996-07-17 09:35:08 +08:00
|
|
|
static void addListEntry(Header h, int_32 tag, char *line);
|
1997-03-31 22:16:11 +08:00
|
|
|
static int finishCurrentPart(Spec spec, StringBuf sb,
|
|
|
|
struct PackageRec *cur_package,
|
1997-07-07 22:51:54 +08:00
|
|
|
int cur_part, char *triggerArgs,
|
|
|
|
char *scriptProg);
|
1996-07-17 09:35:08 +08:00
|
|
|
|
1997-07-25 21:09:05 +08:00
|
|
|
Spec parseSpecAux(FILE *f, char *specfile, char *buildRootOverride,
|
|
|
|
char ***buildArchs);
|
|
|
|
|
1995-12-28 00:50:50 +08:00
|
|
|
/**********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Source and patch structure creation/deletion/lookup */
|
|
|
|
/* */
|
|
|
|
/**********************************************************************/
|
|
|
|
|
|
|
|
static int addSource(Spec spec, char *line)
|
|
|
|
{
|
|
|
|
struct sources *p;
|
|
|
|
char *s, *s1, c;
|
|
|
|
char *file;
|
|
|
|
unsigned long int x;
|
1997-04-15 02:40:23 +08:00
|
|
|
char name[1024], expansion[1024];
|
1995-12-28 00:50:50 +08:00
|
|
|
|
|
|
|
p = malloc(sizeof(struct sources));
|
|
|
|
p->next = spec->sources;
|
|
|
|
spec->sources = p;
|
|
|
|
|
|
|
|
if (! strncasecmp(line, "source", 6)) {
|
1996-01-18 02:16:46 +08:00
|
|
|
spec->numSources++;
|
1995-12-28 00:50:50 +08:00
|
|
|
p->ispatch = 0;
|
|
|
|
s = line + 6;
|
|
|
|
} else if (! strncasecmp(line, "patch", 5)) {
|
1996-01-18 02:16:46 +08:00
|
|
|
spec->numPatches++;
|
1995-12-28 00:50:50 +08:00
|
|
|
p->ispatch = 1;
|
|
|
|
s = line + 5;
|
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADSPEC, "Not a source/patch line: %s\n", line);
|
1995-12-28 00:50:50 +08:00
|
|
|
return(RPMERR_BADSPEC);
|
|
|
|
}
|
|
|
|
|
|
|
|
s += strspn(s, " \t\n");
|
|
|
|
p->num = 0;
|
|
|
|
if (*s != ':') {
|
|
|
|
x = strspn(s, "0123456789");
|
|
|
|
if (! x) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADSPEC, "Bad source/patch line: %s\n", line);
|
1995-12-28 00:50:50 +08:00
|
|
|
return(RPMERR_BADSPEC);
|
|
|
|
}
|
|
|
|
c = s[x];
|
|
|
|
s[x] = '\0';
|
|
|
|
s1 = NULL;
|
|
|
|
p->num = strtoul(s, &s1, 10);
|
|
|
|
if ((*s1) || (s1 == s) || (p->num == ULONG_MAX)) {
|
|
|
|
s[x] = c;
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADSPEC, "Bad source/patch number: %s\n", s);
|
1995-12-28 00:50:50 +08:00
|
|
|
return(RPMERR_BADSPEC);
|
|
|
|
}
|
|
|
|
s[x] = c;
|
|
|
|
s += x;
|
|
|
|
/* skip spaces */
|
|
|
|
s += strspn(s, " \t\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*s != ':') {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADSPEC, "Bad source/patch line: %s\n", line);
|
1995-12-28 00:50:50 +08:00
|
|
|
return(RPMERR_BADSPEC);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip to actual source */
|
|
|
|
s++;
|
|
|
|
s += strspn(s, " \t\n");
|
|
|
|
|
|
|
|
file = strtok(s, " \t\n");
|
|
|
|
if (! file) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADSPEC, "Bad source/patch line: %s\n", line);
|
1995-12-28 00:50:50 +08:00
|
|
|
return(RPMERR_BADSPEC);
|
|
|
|
}
|
|
|
|
p->fullSource = strdup(file);
|
|
|
|
p->source = strrchr(p->fullSource, '/');
|
|
|
|
if (p->source) {
|
|
|
|
p->source++;
|
|
|
|
} else {
|
|
|
|
p->source = p->fullSource;
|
|
|
|
}
|
|
|
|
|
1997-04-15 02:40:23 +08:00
|
|
|
sprintf(expansion, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), p->source);
|
|
|
|
sprintf(name, "%s%d", (p->ispatch) ? "PATCH" : "SOURCE", p->num);
|
|
|
|
addMacro(name, expansion);
|
1997-04-15 04:20:13 +08:00
|
|
|
sprintf(name, "%sURL%d", (p->ispatch) ? "PATCH" : "SOURCE", p->num);
|
|
|
|
addMacro(name, p->fullSource);
|
1997-04-15 02:40:23 +08:00
|
|
|
|
1995-12-28 00:50:50 +08:00
|
|
|
if (p->ispatch) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "Patch(%d) = %s\n", p->num, p->fullSource);
|
1995-12-28 00:50:50 +08:00
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "Source(%d) = %s\n", p->num, p->fullSource);
|
1995-12-28 00:50:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void freeSources(Spec s)
|
|
|
|
{
|
|
|
|
struct sources *p1, *p2;
|
|
|
|
|
|
|
|
p1 = s->sources;
|
|
|
|
while (p1) {
|
|
|
|
p2 = p1;
|
|
|
|
p1 = p1->next;
|
|
|
|
free(p2->fullSource);
|
|
|
|
free(p2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *getSource(Spec s, int ispatch, int num)
|
|
|
|
{
|
|
|
|
struct sources *p = s->sources;
|
|
|
|
|
|
|
|
while (p) {
|
|
|
|
if ((ispatch == p->ispatch) &&
|
|
|
|
(num == p->num)) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p) {
|
|
|
|
return(p->source);
|
|
|
|
} else {
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *getFullSource(Spec s, int ispatch, int num)
|
|
|
|
{
|
|
|
|
struct sources *p = s->sources;
|
|
|
|
|
|
|
|
while (p) {
|
|
|
|
if ((ispatch == p->ispatch) &&
|
|
|
|
(num == p->num)) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p) {
|
|
|
|
return(p->fullSource);
|
|
|
|
} else {
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-06-28 01:22:18 +08:00
|
|
|
int noSourcePatch(Spec s, char *line, int_32 tag)
|
|
|
|
{
|
|
|
|
int_32 array[1024]; /* XXX - max 1024 sources or patches */
|
|
|
|
int_32 num;
|
|
|
|
int count;
|
|
|
|
char *t, *te;
|
|
|
|
|
|
|
|
if (((tag == RPMTAG_NOSOURCE) && s->numNoSource) ||
|
|
|
|
((tag == RPMTAG_NOPATCH) && s->numNoPatch)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADSPEC, "Only one nosource/nopatch line allowed\n");
|
1996-06-28 01:22:18 +08:00
|
|
|
return(RPMERR_BADSPEC);
|
|
|
|
}
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
while ((t = strtok(line, ", \t"))) {
|
|
|
|
num = strtoul(t, &te, 10);
|
|
|
|
if ((*te) || (te == t) || (num == ULONG_MAX)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADSPEC, "Bad source/patch number: %s\n", t);
|
1996-06-28 01:22:18 +08:00
|
|
|
return(RPMERR_BADSPEC);
|
|
|
|
}
|
|
|
|
array[count++] = num;
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "Skipping source/patch number: %d\n", num);
|
1996-06-28 01:22:18 +08:00
|
|
|
line = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
if (tag == RPMTAG_NOSOURCE) {
|
|
|
|
s->numNoSource = count;
|
|
|
|
s->noSource = malloc(sizeof(int_32) * count);
|
|
|
|
memcpy(s->noSource, array, sizeof(int_32) * count);
|
|
|
|
} else {
|
|
|
|
s->numNoPatch = count;
|
|
|
|
s->noPatch = malloc(sizeof(int_32) * count);
|
|
|
|
memcpy(s->noPatch, array, sizeof(int_32) * count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-05-08 02:49:33 +08:00
|
|
|
/**********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Provide/Require handling */
|
|
|
|
/* */
|
|
|
|
/**********************************************************************/
|
|
|
|
|
1996-06-08 02:31:08 +08:00
|
|
|
static void free_reqprov(struct ReqProv *p)
|
1996-05-08 02:49:33 +08:00
|
|
|
{
|
1996-06-08 02:31:08 +08:00
|
|
|
struct ReqProv *s;
|
1996-05-08 02:49:33 +08:00
|
|
|
|
1996-06-08 02:31:08 +08:00
|
|
|
while (p) {
|
|
|
|
s = p;
|
|
|
|
p = p->next;
|
|
|
|
FREE(s->name);
|
|
|
|
FREE(s->version);
|
|
|
|
free(s);
|
1996-05-08 02:49:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-11-15 01:36:01 +08:00
|
|
|
struct ReqComp ReqComparisons[] = {
|
1996-11-19 02:02:36 +08:00
|
|
|
{ "<=", RPMSENSE_LESS | RPMSENSE_EQUAL},
|
|
|
|
{ "<=S", RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_SERIAL},
|
|
|
|
{ "=<", RPMSENSE_LESS | RPMSENSE_EQUAL},
|
|
|
|
{ "=<S", RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_SERIAL},
|
|
|
|
{ "<", RPMSENSE_LESS},
|
|
|
|
{ "<S", RPMSENSE_LESS | RPMSENSE_SERIAL},
|
|
|
|
|
|
|
|
{ "=", RPMSENSE_EQUAL},
|
|
|
|
{ "=S", RPMSENSE_EQUAL | RPMSENSE_SERIAL},
|
1996-05-08 02:49:33 +08:00
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
{ ">=", RPMSENSE_GREATER | RPMSENSE_EQUAL},
|
|
|
|
{ ">=S", RPMSENSE_GREATER | RPMSENSE_EQUAL | RPMSENSE_SERIAL},
|
|
|
|
{ "=>", RPMSENSE_GREATER | RPMSENSE_EQUAL},
|
|
|
|
{ "=>S", RPMSENSE_GREATER | RPMSENSE_EQUAL | RPMSENSE_SERIAL},
|
|
|
|
{ ">", RPMSENSE_GREATER},
|
|
|
|
{ ">S", RPMSENSE_GREATER | RPMSENSE_SERIAL},
|
1996-05-08 02:49:33 +08:00
|
|
|
{ NULL, 0 },
|
|
|
|
};
|
|
|
|
|
1996-06-28 04:15:53 +08:00
|
|
|
static int parseRequiresConflicts(struct PackageRec *p, char *line,
|
|
|
|
int flag)
|
1996-05-08 02:49:33 +08:00
|
|
|
{
|
|
|
|
char *req = NULL;
|
|
|
|
char *version = NULL;
|
|
|
|
int flags;
|
|
|
|
struct ReqComp *rc;
|
|
|
|
|
|
|
|
while (req || (req = strtok(line, " ,\t\n"))) {
|
1997-06-20 03:46:19 +08:00
|
|
|
switch (flag) {
|
|
|
|
case RPMTAG_CONFLICTFLAGS:
|
|
|
|
flags = RPMSENSE_CONFLICTS;
|
|
|
|
break;
|
|
|
|
case RPMTAG_PREREQ:
|
|
|
|
flags = RPMSENSE_PREREQ;
|
|
|
|
break;
|
1997-09-17 03:20:16 +08:00
|
|
|
case RPMTAG_OBSOLETES:
|
|
|
|
flags = RPMSENSE_OBSOLETES;
|
|
|
|
break;
|
1997-06-20 03:46:19 +08:00
|
|
|
default:
|
|
|
|
flags = RPMSENSE_ANY;
|
|
|
|
break;
|
|
|
|
}
|
1997-05-02 01:22:35 +08:00
|
|
|
if (flag == RPMTAG_CONFLICTFLAGS && req[0] == '/') {
|
|
|
|
rpmError(RPMERR_BADSPEC,
|
|
|
|
"No file names in Conflicts: %s", req);
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
1997-09-17 03:20:16 +08:00
|
|
|
if (flag == RPMTAG_OBSOLETES && req[0] == '/') {
|
|
|
|
rpmError(RPMERR_BADSPEC,
|
|
|
|
"No file names in Obsoletes: %s", req);
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
1996-05-08 02:49:33 +08:00
|
|
|
if ((version = strtok(NULL, " ,\t\n"))) {
|
|
|
|
rc = ReqComparisons;
|
|
|
|
while (rc->token && strcmp(version, rc->token)) {
|
|
|
|
rc++;
|
|
|
|
}
|
|
|
|
if (rc->token) {
|
1997-05-02 01:22:35 +08:00
|
|
|
if (req[0] == '/') {
|
|
|
|
rpmError(RPMERR_BADSPEC,
|
|
|
|
"No versions on file names in Requires: %s", req);
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
1997-08-29 22:04:58 +08:00
|
|
|
if (flag == RPMTAG_PREREQ) {
|
|
|
|
rpmError(RPMERR_BADSPEC,
|
|
|
|
"No versions in PreReq: %s", req);
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
1997-09-17 03:20:16 +08:00
|
|
|
if (flag == RPMTAG_OBSOLETES) {
|
|
|
|
rpmError(RPMERR_BADSPEC,
|
|
|
|
"No versions in Obsoletes: %s", req);
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
1996-05-08 02:49:33 +08:00
|
|
|
/* read a version */
|
1997-01-28 23:33:55 +08:00
|
|
|
flags |= rc->flags;
|
1996-05-08 02:49:33 +08:00
|
|
|
version = strtok(NULL, " ,\t\n");
|
|
|
|
}
|
|
|
|
}
|
1996-11-19 02:02:36 +08:00
|
|
|
if ((flags & RPMSENSE_SENSEMASK) && !version) {
|
|
|
|
rpmError(RPMERR_BADSPEC, "Version required in require/conflict");
|
1996-05-08 02:49:33 +08:00
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
|
|
|
|
1997-01-28 23:33:55 +08:00
|
|
|
addReqProv(p, flags, req,
|
|
|
|
(flags & RPMSENSE_SENSEMASK) ? version : NULL);
|
1996-05-08 02:49:33 +08:00
|
|
|
|
|
|
|
req = NULL;
|
1997-01-28 23:33:55 +08:00
|
|
|
if (! (flags & RPMSENSE_SENSEMASK)) {
|
1996-05-08 02:49:33 +08:00
|
|
|
/* No version -- we just read a name */
|
|
|
|
req = version;
|
|
|
|
}
|
|
|
|
line = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-06-08 02:31:08 +08:00
|
|
|
static int parseProvides(struct PackageRec *p, char *line)
|
1996-05-08 02:49:33 +08:00
|
|
|
{
|
1996-06-08 02:31:08 +08:00
|
|
|
char *prov;
|
1996-11-19 02:02:36 +08:00
|
|
|
int flags = RPMSENSE_PROVIDES;
|
1996-05-08 02:49:33 +08:00
|
|
|
|
1996-06-08 02:31:08 +08:00
|
|
|
while ((prov = strtok(line, " ,\t\n"))) {
|
1997-05-02 01:22:35 +08:00
|
|
|
if (prov[0] == '/') {
|
|
|
|
rpmError(RPMERR_BADSPEC,
|
|
|
|
"No file names in provides: %s", prov);
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
1996-06-08 02:31:08 +08:00
|
|
|
addReqProv(p, flags, prov, NULL);
|
|
|
|
line = NULL;
|
1996-05-08 02:49:33 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1995-12-14 23:52:51 +08:00
|
|
|
/**********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Spec and package structure creation/deletion/lookup */
|
|
|
|
/* */
|
|
|
|
/**********************************************************************/
|
|
|
|
|
1995-12-13 23:57:59 +08:00
|
|
|
static struct PackageRec *new_packagerec(void)
|
|
|
|
{
|
|
|
|
struct PackageRec *p = malloc(sizeof(struct PackageRec));
|
|
|
|
|
|
|
|
p->subname = NULL;
|
|
|
|
p->newname = NULL;
|
1996-01-08 15:03:21 +08:00
|
|
|
p->icon = NULL;
|
1996-11-19 02:02:36 +08:00
|
|
|
p->header = headerNew();
|
1995-12-13 23:57:59 +08:00
|
|
|
p->filelist = newStringBuf();
|
1995-12-20 01:56:45 +08:00
|
|
|
p->files = -1; /* -1 means no %files, thus no package */
|
1996-05-08 02:49:33 +08:00
|
|
|
p->fileFile = NULL;
|
1996-02-23 10:22:18 +08:00
|
|
|
p->doc = newStringBuf();
|
1996-05-08 02:49:33 +08:00
|
|
|
p->reqprov = NULL;
|
|
|
|
p->numReq = 0;
|
|
|
|
p->numProv = 0;
|
1996-06-28 04:15:53 +08:00
|
|
|
p->numConflict = 0;
|
1997-06-20 03:46:19 +08:00
|
|
|
p->numPreReq = 0;
|
1996-11-15 01:36:01 +08:00
|
|
|
p->trigger.alloced = 0;
|
|
|
|
p->trigger.used = 0;
|
|
|
|
p->trigger.triggerScripts = NULL;
|
|
|
|
p->trigger.trigger = NULL;
|
|
|
|
p->trigger.triggerCount = 0;
|
1995-12-13 23:57:59 +08:00
|
|
|
p->next = NULL;
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
1995-12-12 06:52:59 +08:00
|
|
|
void free_packagerec(struct PackageRec *p)
|
|
|
|
{
|
1997-07-25 21:09:05 +08:00
|
|
|
if (! p ) return;
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
headerFree(p->header);
|
1995-12-13 23:57:59 +08:00
|
|
|
freeStringBuf(p->filelist);
|
1996-02-23 10:22:18 +08:00
|
|
|
freeStringBuf(p->doc);
|
1995-12-13 01:53:17 +08:00
|
|
|
FREE(p->subname);
|
|
|
|
FREE(p->newname);
|
1996-01-08 15:03:21 +08:00
|
|
|
FREE(p->icon);
|
1996-05-08 02:49:33 +08:00
|
|
|
FREE(p->fileFile);
|
|
|
|
free_reqprov(p->reqprov);
|
1996-11-15 01:36:01 +08:00
|
|
|
freeTriggers(p->trigger);
|
1995-12-12 06:52:59 +08:00
|
|
|
if (p->next) {
|
|
|
|
free_packagerec(p->next);
|
|
|
|
}
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void freeSpec(Spec s)
|
1995-11-28 06:31:21 +08:00
|
|
|
{
|
1995-12-13 01:53:17 +08:00
|
|
|
FREE(s->name);
|
1996-01-08 15:03:21 +08:00
|
|
|
FREE(s->specfile);
|
1996-06-28 01:22:18 +08:00
|
|
|
FREE(s->noSource);
|
|
|
|
FREE(s->noPatch);
|
1996-07-15 00:06:35 +08:00
|
|
|
FREE(s->buildroot);
|
1997-07-25 21:09:05 +08:00
|
|
|
FREE(s->buildArch);
|
1995-12-28 00:50:50 +08:00
|
|
|
freeSources(s);
|
1995-12-13 23:57:59 +08:00
|
|
|
freeStringBuf(s->prep);
|
|
|
|
freeStringBuf(s->build);
|
|
|
|
freeStringBuf(s->install);
|
1996-01-29 11:31:39 +08:00
|
|
|
freeStringBuf(s->doc);
|
1995-12-13 23:57:59 +08:00
|
|
|
freeStringBuf(s->clean);
|
1995-12-12 06:52:59 +08:00
|
|
|
free_packagerec(s->packages);
|
1995-11-28 06:31:21 +08:00
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
|
1995-12-14 23:52:51 +08:00
|
|
|
#define LP_CREATE 1
|
|
|
|
#define LP_FAIL_EXISTS (1 << 1)
|
|
|
|
#define LP_SUBNAME (1 << 2)
|
|
|
|
#define LP_NEWNAME (1 << 3)
|
|
|
|
|
|
|
|
int lookup_package(Spec s, struct PackageRec **pr, char *name, int flags)
|
|
|
|
{
|
|
|
|
struct PackageRec *package;
|
|
|
|
struct PackageRec **ppp;
|
|
|
|
|
|
|
|
package = s->packages;
|
|
|
|
while (package) {
|
|
|
|
if (flags & LP_SUBNAME) {
|
1996-02-17 01:26:43 +08:00
|
|
|
if (! package->subname) {
|
|
|
|
package = package->next;
|
|
|
|
continue;
|
|
|
|
}
|
1995-12-14 23:52:51 +08:00
|
|
|
if (! strcmp(package->subname, name)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (flags & LP_NEWNAME) {
|
1996-02-17 01:26:43 +08:00
|
|
|
if (! package->newname) {
|
|
|
|
package = package->next;
|
|
|
|
continue;
|
|
|
|
}
|
1995-12-14 23:52:51 +08:00
|
|
|
if (! strcmp(package->newname, name)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Base package */
|
1996-02-17 01:26:43 +08:00
|
|
|
if ((! package->newname) && (! package->subname)) {
|
1995-12-14 23:52:51 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
package = package->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (package && (flags & LP_FAIL_EXISTS)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (package) {
|
|
|
|
*pr = package;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* At this point the package does not exist */
|
|
|
|
|
|
|
|
if (! (flags & LP_CREATE)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create it */
|
|
|
|
package = new_packagerec();
|
1995-12-20 05:06:39 +08:00
|
|
|
if (name) {
|
1996-02-22 01:19:52 +08:00
|
|
|
if (flags & LP_SUBNAME) {
|
|
|
|
package->subname = strdup(name);
|
|
|
|
} else if (flags & LP_NEWNAME) {
|
|
|
|
package->newname = strdup(name);
|
|
|
|
}
|
1995-12-14 23:52:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Link it in to the spec */
|
|
|
|
ppp = &(s->packages);
|
|
|
|
while (*ppp) {
|
|
|
|
ppp = &((*ppp)->next);
|
|
|
|
}
|
|
|
|
*ppp = package;
|
|
|
|
|
|
|
|
*pr = package;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1997-04-15 04:05:43 +08:00
|
|
|
static void generateNames(Spec s)
|
1996-02-22 01:19:52 +08:00
|
|
|
{
|
|
|
|
struct PackageRec *package;
|
|
|
|
char buf[1024];
|
1997-04-15 04:05:43 +08:00
|
|
|
char *name;
|
1996-02-22 01:19:52 +08:00
|
|
|
|
|
|
|
package = s->packages;
|
|
|
|
while (package) {
|
|
|
|
if (package->subname) {
|
|
|
|
sprintf(buf, "%s-%s", s->name, package->subname);
|
1996-02-23 10:22:18 +08:00
|
|
|
name = buf;
|
1996-02-22 01:19:52 +08:00
|
|
|
} else if (package->newname) {
|
1996-02-23 10:22:18 +08:00
|
|
|
name = package->newname;
|
1996-02-22 01:19:52 +08:00
|
|
|
} else {
|
|
|
|
/* Must be the main package */
|
1996-02-23 10:22:18 +08:00
|
|
|
name = s->name;
|
|
|
|
}
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(package->header, RPMTAG_NAME, RPM_STRING_TYPE, name, 1);
|
1996-02-23 10:22:18 +08:00
|
|
|
|
1996-02-22 01:19:52 +08:00
|
|
|
package = package->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-01-25 12:48:06 +08:00
|
|
|
/* datestr is of the form 'Wed Jan 1 1997' */
|
|
|
|
static int dateToTimet(const char * datestr, time_t * secs)
|
|
|
|
{
|
|
|
|
struct tm time;
|
|
|
|
char * chptr, * end, ** idx;
|
|
|
|
char * date = strcpy(alloca(strlen(datestr) + 1), datestr);
|
|
|
|
static char * days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
|
|
|
|
NULL };
|
|
|
|
static char * months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
|
1997-08-31 21:58:57 +08:00
|
|
|
static char lengths[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
1997-01-25 12:48:06 +08:00
|
|
|
|
|
|
|
memset(&time, 0, sizeof(time));
|
|
|
|
|
|
|
|
end = chptr = date;
|
|
|
|
|
|
|
|
/* day of week */
|
|
|
|
if ((chptr = strtok(date, " \t\n")) == NULL) return -1;
|
|
|
|
idx = days;
|
|
|
|
while (*idx && strcmp(*idx, chptr)) idx++;
|
|
|
|
if (!*idx) return -1;
|
|
|
|
|
|
|
|
/* month */
|
|
|
|
if ((chptr = strtok(NULL, " \t\n")) == NULL) return -1;
|
|
|
|
idx = months;
|
|
|
|
while (*idx && strcmp(*idx, chptr)) idx++;
|
|
|
|
if (!*idx) return -1;
|
|
|
|
|
|
|
|
time.tm_mon = idx - months;
|
|
|
|
|
|
|
|
/* day */
|
|
|
|
if ((chptr = strtok(NULL, " \t\n")) == NULL) return -1;
|
|
|
|
|
1997-01-31 04:09:42 +08:00
|
|
|
/* make this noon so the day is always right (as we make this UTC) */
|
|
|
|
time.tm_hour = 12;
|
|
|
|
|
1997-01-25 12:48:06 +08:00
|
|
|
time.tm_mday = strtol(chptr, &chptr, 10);
|
|
|
|
if (*chptr) return -1;
|
|
|
|
if (time.tm_mday < 0 || time.tm_mday > lengths[time.tm_mon]) return -1;
|
|
|
|
|
|
|
|
/* year */
|
|
|
|
if ((chptr = strtok(NULL, " \t\n")) == NULL) return -1;
|
|
|
|
|
|
|
|
time.tm_year = strtol(chptr, &chptr, 10);
|
|
|
|
if (*chptr) return -1;
|
|
|
|
if (time.tm_year < 1997 || time.tm_year >= 3000) return -1;
|
|
|
|
time.tm_year -= 1900;
|
|
|
|
|
|
|
|
*secs = mktime(&time);
|
|
|
|
if (*secs == -1) return -1;
|
|
|
|
|
|
|
|
/* adjust to GMT */
|
|
|
|
*secs += timezone;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void addChangelogEntry(Header h, int time, char *name, char *text)
|
|
|
|
{
|
|
|
|
if (headerIsEntry(h, RPMTAG_CHANGELOGTIME)) {
|
|
|
|
headerAppendEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE,
|
|
|
|
&time, 1);
|
|
|
|
headerAppendEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE,
|
|
|
|
&name, 1);
|
|
|
|
headerAppendEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE,
|
|
|
|
&text, 1);
|
|
|
|
} else {
|
|
|
|
headerAddEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE,
|
|
|
|
&time, 1);
|
|
|
|
headerAddEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE,
|
|
|
|
&name, 1);
|
|
|
|
headerAddEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE,
|
|
|
|
&text, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int addChangelog(Header h, StringBuf sb)
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
int i;
|
|
|
|
int time, lastTime = 0;
|
|
|
|
char *date, *name, *text, *next;
|
|
|
|
|
|
|
|
s = getStringBuf(sb);
|
|
|
|
|
|
|
|
/* skip space */
|
|
|
|
while (*s && isspace(*s)) s++;
|
|
|
|
|
|
|
|
while (*s) {
|
|
|
|
if (*s != '*') {
|
|
|
|
rpmError(RPMERR_BADSPEC, "%%changelog entries must start with *");
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find end of line */
|
|
|
|
date = s;
|
|
|
|
while (*s && *s != '\n') s++;
|
|
|
|
if (! *s) {
|
|
|
|
rpmError(RPMERR_BADSPEC, "incomplete %%changelog entry");
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
|
|
|
*s = '\0';
|
|
|
|
text = s + 1;
|
|
|
|
|
|
|
|
/* 4 fields of date */
|
|
|
|
date++;
|
|
|
|
s = date;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
while (*s && isspace(*s)) s++;
|
|
|
|
while (*s && !isspace(*s)) s++;
|
|
|
|
}
|
|
|
|
while (isspace(*date)) date++;
|
|
|
|
if (dateToTimet(date, (time_t *)&time)) {
|
|
|
|
rpmError(RPMERR_BADSPEC, "bad date in %%changelog: %s", date);
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
|
|
|
if (lastTime && lastTime < time) {
|
|
|
|
rpmError(RPMERR_BADSPEC,
|
|
|
|
"%%changelog not in decending chronological order");
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
|
|
|
lastTime = time;
|
|
|
|
|
|
|
|
/* skip space to the name */
|
|
|
|
while (*s && isspace(*s)) s++;
|
|
|
|
if (! *s) {
|
|
|
|
rpmError(RPMERR_BADSPEC, "missing name in %%changelog");
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* name */
|
|
|
|
name = s;
|
|
|
|
while (*s) s++;
|
|
|
|
while (s > name && isspace(*s)) {
|
|
|
|
*s-- = '\0';
|
|
|
|
}
|
|
|
|
if (s == name) {
|
|
|
|
rpmError(RPMERR_BADSPEC, "missing name in %%changelog");
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* text */
|
|
|
|
while (*text && isspace(*text)) text++;
|
|
|
|
if (! *text) {
|
|
|
|
rpmError(RPMERR_BADSPEC, "no description in %%changelog");
|
|
|
|
return RPMERR_BADSPEC;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find the next leading '*' (or eos) */
|
|
|
|
s = text;
|
|
|
|
do {
|
1997-03-12 01:12:42 +08:00
|
|
|
s++;
|
|
|
|
} while (*s && (*(s-1) != '\n' || *s != '*'));
|
1997-01-25 12:48:06 +08:00
|
|
|
next = s;
|
|
|
|
s--;
|
|
|
|
|
|
|
|
/* backup to end of description */
|
|
|
|
while ((s > text) && isspace(*s)) {
|
|
|
|
*s-- = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
addChangelogEntry(h, time, name, text);
|
|
|
|
s = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1995-12-14 23:52:51 +08:00
|
|
|
/**********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Line reading */
|
|
|
|
/* */
|
|
|
|
/**********************************************************************/
|
|
|
|
|
1995-11-28 06:31:21 +08:00
|
|
|
static int match_arch(char *s)
|
|
|
|
{
|
1995-12-28 00:50:50 +08:00
|
|
|
char *tok, *arch;
|
|
|
|
int sense, match;
|
|
|
|
|
1997-07-23 09:06:03 +08:00
|
|
|
rpmGetArchInfo(&arch, NULL);
|
1995-12-28 00:50:50 +08:00
|
|
|
match = 0;
|
|
|
|
|
|
|
|
tok = strtok(s, " \n\t");
|
|
|
|
sense = (! strcmp(tok, "%ifarch")) ? 1 : 0;
|
|
|
|
|
|
|
|
while ((tok = strtok(NULL, " \n\t"))) {
|
|
|
|
if (! strcmp(tok, arch)) {
|
|
|
|
match |= 1;
|
|
|
|
}
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
1995-12-28 00:50:50 +08:00
|
|
|
|
|
|
|
return (sense == match);
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int match_os(char *s)
|
|
|
|
{
|
1995-12-28 00:50:50 +08:00
|
|
|
char *tok, *os;
|
|
|
|
int sense, match;
|
|
|
|
|
1997-07-23 09:06:03 +08:00
|
|
|
rpmGetOsInfo(&os, NULL);
|
1995-12-28 00:50:50 +08:00
|
|
|
match = 0;
|
|
|
|
|
|
|
|
tok = strtok(s, " \n\t");
|
|
|
|
sense = (! strcmp(tok, "%ifos")) ? 1 : 0;
|
|
|
|
|
|
|
|
while ((tok = strtok(NULL, " \n\t"))) {
|
|
|
|
if (! strcmp(tok, os)) {
|
|
|
|
match |= 1;
|
|
|
|
}
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
1995-12-28 00:50:50 +08:00
|
|
|
|
|
|
|
return (sense == match);
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
static struct read_level_entry {
|
|
|
|
int reading; /* 1 if we are reading at this level */
|
|
|
|
struct read_level_entry *next;
|
|
|
|
} *read_level = NULL;
|
1995-11-28 06:31:21 +08:00
|
|
|
|
|
|
|
static int read_line(FILE *f, char *line)
|
|
|
|
{
|
1995-12-13 01:53:17 +08:00
|
|
|
static struct read_level_entry *rl;
|
|
|
|
int gotline;
|
|
|
|
char *r;
|
1997-06-04 05:45:09 +08:00
|
|
|
char *firstChar;
|
1995-11-28 06:31:21 +08:00
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
do {
|
|
|
|
gotline = 0;
|
|
|
|
if (! fgets(line, LINE_BUF_SIZE, f)) {
|
|
|
|
/* the end */
|
|
|
|
if (read_level->next) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_UNMATCHEDIF, "Unclosed %%if");
|
1995-12-13 01:53:17 +08:00
|
|
|
return RPMERR_UNMATCHEDIF;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
1997-06-04 05:45:09 +08:00
|
|
|
firstChar = line;
|
|
|
|
while (*firstChar && isspace(*firstChar)) {
|
|
|
|
firstChar++;
|
|
|
|
}
|
|
|
|
if ((! strncmp("%ifarch", firstChar, 7)) ||
|
|
|
|
(! strncmp("%ifnarch", firstChar, 8))) {
|
1997-04-11 02:56:31 +08:00
|
|
|
expandMacros(line);
|
1995-12-13 01:53:17 +08:00
|
|
|
rl = malloc(sizeof(struct read_level_entry));
|
|
|
|
rl->next = read_level;
|
|
|
|
rl->reading = read_level->reading && match_arch(line);
|
|
|
|
read_level = rl;
|
1997-06-04 05:45:09 +08:00
|
|
|
} else if ((! strncmp("%ifos", firstChar, 5)) ||
|
|
|
|
(! strncmp("%ifnos", firstChar, 6))) {
|
1997-04-11 02:56:31 +08:00
|
|
|
expandMacros(line);
|
1995-12-13 01:53:17 +08:00
|
|
|
rl = malloc(sizeof(struct read_level_entry));
|
|
|
|
rl->next = read_level;
|
|
|
|
rl->reading = read_level->reading && match_os(line);
|
|
|
|
read_level = rl;
|
1997-06-04 05:45:09 +08:00
|
|
|
} else if (! strncmp("%else", firstChar, 5)) {
|
1997-04-11 02:56:31 +08:00
|
|
|
expandMacros(line);
|
1995-12-13 01:53:17 +08:00
|
|
|
if (! read_level->next) {
|
|
|
|
/* Got an else with no %if ! */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_UNMATCHEDIF, "Got a %%else with no if");
|
1995-12-13 01:53:17 +08:00
|
|
|
return RPMERR_UNMATCHEDIF;
|
|
|
|
}
|
|
|
|
read_level->reading =
|
|
|
|
read_level->next->reading && ! read_level->reading;
|
1997-06-04 05:45:09 +08:00
|
|
|
} else if (! strncmp("%endif", firstChar, 6)) {
|
1997-04-11 02:56:31 +08:00
|
|
|
expandMacros(line);
|
1996-02-21 23:29:20 +08:00
|
|
|
if (! read_level->next) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_UNMATCHEDIF, "Got a %%endif with no if");
|
1996-02-20 05:16:15 +08:00
|
|
|
return RPMERR_UNMATCHEDIF;
|
|
|
|
}
|
1995-12-13 01:53:17 +08:00
|
|
|
rl = read_level;
|
|
|
|
read_level = rl->next;
|
|
|
|
free(rl);
|
|
|
|
} else {
|
1997-04-11 02:56:31 +08:00
|
|
|
if (read_level->reading) {
|
|
|
|
expandMacros(line);
|
|
|
|
}
|
1995-12-13 01:53:17 +08:00
|
|
|
gotline = 1;
|
|
|
|
}
|
|
|
|
} while (! (gotline && read_level->reading));
|
|
|
|
|
|
|
|
r = line + (strlen(line)) - 1;
|
1996-05-23 01:38:46 +08:00
|
|
|
while (isspace(*r)) {
|
|
|
|
*(r--) = '\0';
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
1995-12-13 01:53:17 +08:00
|
|
|
return 1;
|
|
|
|
}
|
1995-11-28 06:31:21 +08:00
|
|
|
|
1995-12-14 23:52:51 +08:00
|
|
|
/**********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Line parsing */
|
|
|
|
/* */
|
|
|
|
/**********************************************************************/
|
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
struct preamble_line {
|
|
|
|
int tag;
|
|
|
|
int len;
|
|
|
|
char *token;
|
|
|
|
} preamble_spec[] = {
|
1996-06-28 04:15:53 +08:00
|
|
|
{RPMTAG_NAME, 0, "name"},
|
|
|
|
{RPMTAG_VERSION, 0, "version"},
|
|
|
|
{RPMTAG_RELEASE, 0, "release"},
|
|
|
|
{RPMTAG_SERIAL, 0, "serial"},
|
|
|
|
{RPMTAG_DESCRIPTION, 0, "description"},
|
|
|
|
{RPMTAG_SUMMARY, 0, "summary"},
|
|
|
|
{RPMTAG_COPYRIGHT, 0, "copyright"},
|
|
|
|
{RPMTAG_DISTRIBUTION, 0, "distribution"},
|
|
|
|
{RPMTAG_VENDOR, 0, "vendor"},
|
|
|
|
{RPMTAG_GROUP, 0, "group"},
|
|
|
|
{RPMTAG_PACKAGER, 0, "packager"},
|
|
|
|
{RPMTAG_URL, 0, "url"},
|
|
|
|
{RPMTAG_ROOT, 0, "root"},
|
|
|
|
{RPMTAG_SOURCE, 0, "source"},
|
|
|
|
{RPMTAG_PATCH, 0, "patch"},
|
|
|
|
{RPMTAG_NOSOURCE, 0, "nosource"},
|
|
|
|
{RPMTAG_NOPATCH, 0, "nopatch"},
|
1996-07-17 09:35:08 +08:00
|
|
|
{RPMTAG_EXCLUDEARCH, 0, "excludearch"},
|
|
|
|
{RPMTAG_EXCLUSIVEARCH, 0, "exclusivearch"},
|
|
|
|
{RPMTAG_EXCLUDEOS, 0, "excludeos"},
|
|
|
|
{RPMTAG_EXCLUSIVEOS, 0, "exclusiveos"},
|
1996-06-28 04:15:53 +08:00
|
|
|
{RPMTAG_EXCLUDE, 0, "exclude"},
|
|
|
|
{RPMTAG_EXCLUSIVE, 0, "exclusive"},
|
|
|
|
{RPMTAG_ICON, 0, "icon"},
|
|
|
|
{RPMTAG_PROVIDES, 0, "provides"},
|
|
|
|
{RPMTAG_REQUIREFLAGS, 0, "requires"},
|
1997-06-20 03:46:19 +08:00
|
|
|
{RPMTAG_PREREQ, 0, "prereq"},
|
1996-06-28 04:15:53 +08:00
|
|
|
{RPMTAG_CONFLICTFLAGS, 0, "conflicts"},
|
1997-09-17 03:20:16 +08:00
|
|
|
{RPMTAG_OBSOLETES, 0, "obsoletes"},
|
1996-07-09 10:06:26 +08:00
|
|
|
{RPMTAG_DEFAULTPREFIX, 0, "prefix"},
|
1996-07-17 09:35:08 +08:00
|
|
|
{RPMTAG_BUILDROOT, 0, "buildroot"},
|
1997-07-25 21:09:05 +08:00
|
|
|
{RPMTAG_BUILDARCHS, 0, "buildarchitectures"},
|
1996-08-30 02:32:01 +08:00
|
|
|
{RPMTAG_AUTOREQPROV, 0, "autoreqprov"},
|
1995-12-13 01:53:17 +08:00
|
|
|
{0, 0, 0}
|
|
|
|
};
|
1995-11-28 06:31:21 +08:00
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
static int find_preamble_line(char *line, char **s)
|
|
|
|
{
|
|
|
|
struct preamble_line *p = preamble_spec;
|
1995-11-28 06:31:21 +08:00
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
while (p->token && strncasecmp(line, p->token, p->len)) {
|
|
|
|
p++;
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
1996-02-23 04:01:56 +08:00
|
|
|
if (!p->token) return 0;
|
1995-12-13 01:53:17 +08:00
|
|
|
*s = line + p->len;
|
1996-02-23 04:28:19 +08:00
|
|
|
|
|
|
|
/* Unless this is a source or a patch, a ':' better be next */
|
|
|
|
if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) {
|
|
|
|
*s += strspn(*s, " \t");
|
|
|
|
if (**s != ':') {
|
|
|
|
return 0;
|
|
|
|
}
|
1996-02-23 04:01:56 +08:00
|
|
|
}
|
1996-02-23 04:28:19 +08:00
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
*s += strspn(*s, ": \t");
|
|
|
|
return p->tag;
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
/* None of these can be 0 !! */
|
1996-11-15 05:57:24 +08:00
|
|
|
#define PREAMBLE_PART 1
|
|
|
|
#define PREP_PART 2
|
|
|
|
#define BUILD_PART 3
|
|
|
|
#define INSTALL_PART 4
|
|
|
|
#define CLEAN_PART 5
|
|
|
|
#define PREIN_PART 6
|
|
|
|
#define POSTIN_PART 7
|
|
|
|
#define PREUN_PART 8
|
|
|
|
#define POSTUN_PART 9
|
|
|
|
#define FILES_PART 10
|
|
|
|
#define CHANGELOG_PART 11
|
|
|
|
#define DESCRIPTION_PART 12
|
1997-05-02 01:26:56 +08:00
|
|
|
#define TRIGGERIN_PART 13
|
|
|
|
#define TRIGGERUN_PART 14
|
1996-11-15 05:57:24 +08:00
|
|
|
#define VERIFYSCRIPT_PART 15
|
1995-12-13 01:53:17 +08:00
|
|
|
|
|
|
|
static struct part_rec {
|
|
|
|
int part;
|
|
|
|
int len;
|
1995-12-12 06:52:59 +08:00
|
|
|
char *s;
|
1995-12-13 01:53:17 +08:00
|
|
|
} part_list[] = {
|
1996-07-03 02:44:09 +08:00
|
|
|
{PREAMBLE_PART, 0, "%package"},
|
|
|
|
{PREP_PART, 0, "%prep"},
|
|
|
|
{BUILD_PART, 0, "%build"},
|
|
|
|
{INSTALL_PART, 0, "%install"},
|
|
|
|
{CLEAN_PART, 0, "%clean"},
|
|
|
|
{PREUN_PART, 0, "%preun"},
|
|
|
|
{POSTUN_PART, 0, "%postun"},
|
|
|
|
{PREIN_PART, 0, "%pre"},
|
|
|
|
{POSTIN_PART, 0, "%post"},
|
|
|
|
{FILES_PART, 0, "%files"},
|
|
|
|
{CHANGELOG_PART, 0, "%changelog"},
|
|
|
|
{DESCRIPTION_PART, 0, "%description"},
|
1997-05-02 01:26:56 +08:00
|
|
|
{TRIGGERUN_PART, 0, "%triggerun"},
|
|
|
|
{TRIGGERIN_PART, 0, "%trigger"},
|
1996-11-15 05:57:24 +08:00
|
|
|
{VERIFYSCRIPT_PART, 0, "%verifyscript"},
|
1995-12-13 01:53:17 +08:00
|
|
|
{0, 0, 0}
|
1995-12-12 06:52:59 +08:00
|
|
|
};
|
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
static int check_part(char *line, char **s)
|
1995-12-12 06:52:59 +08:00
|
|
|
{
|
1995-12-13 01:53:17 +08:00
|
|
|
struct part_rec *p = part_list;
|
|
|
|
|
1997-04-16 23:50:37 +08:00
|
|
|
while (p->s && strncmp(line, p->s, p->len)) {
|
1995-12-13 01:53:17 +08:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (!p) return 0;
|
|
|
|
*s = line + p->len;
|
|
|
|
*s += strspn(*s, " \t");
|
|
|
|
if (**s == '\0') {
|
|
|
|
*s = NULL;
|
1995-12-12 06:52:59 +08:00
|
|
|
}
|
1995-12-13 01:53:17 +08:00
|
|
|
return p->part;
|
1995-12-12 06:52:59 +08:00
|
|
|
}
|
|
|
|
|
1996-05-08 02:49:33 +08:00
|
|
|
#if 0
|
1996-02-23 10:22:18 +08:00
|
|
|
static char *chop_line(char *s)
|
1995-12-14 23:52:51 +08:00
|
|
|
{
|
|
|
|
char *p, *e;
|
|
|
|
|
|
|
|
p = s;
|
|
|
|
p += strspn(s, " \t");
|
|
|
|
if (*p == '\0') {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
e = s + strlen(s) - 1;
|
|
|
|
while (index(" \t", *e)) {
|
|
|
|
e--;
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
1996-05-08 02:49:33 +08:00
|
|
|
#endif
|
1995-12-14 23:52:51 +08:00
|
|
|
|
1996-07-17 09:35:08 +08:00
|
|
|
static void addListEntry(Header h, int_32 tag, char *line)
|
|
|
|
{
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
|
|
|
char **argvs;
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
argvs = argv = malloc(strlen(line) * sizeof(char *));
|
|
|
|
argc = 0;
|
1996-07-17 12:57:28 +08:00
|
|
|
while ((s = strtok(line, " \t"))) {
|
1996-07-17 09:35:08 +08:00
|
|
|
*argv = s;
|
|
|
|
argc++;
|
|
|
|
argv++;
|
|
|
|
line = NULL;
|
|
|
|
}
|
|
|
|
if (argc) {
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(h, tag, RPM_STRING_ARRAY_TYPE, argvs, argc);
|
1996-07-17 09:35:08 +08:00
|
|
|
}
|
1996-07-18 11:00:16 +08:00
|
|
|
free(argvs);
|
1996-07-17 09:35:08 +08:00
|
|
|
}
|
|
|
|
|
1997-03-31 22:16:11 +08:00
|
|
|
static int finishCurrentPart(Spec spec, StringBuf sb,
|
|
|
|
struct PackageRec *cur_package,
|
1997-07-07 22:51:54 +08:00
|
|
|
int cur_part, char *triggerArgs,
|
|
|
|
char *scriptProg)
|
1997-03-31 22:16:11 +08:00
|
|
|
{
|
|
|
|
int t1 = 0;
|
1997-07-07 22:51:54 +08:00
|
|
|
int t2 = 0;
|
1997-03-31 22:16:11 +08:00
|
|
|
|
1997-07-04 00:34:12 +08:00
|
|
|
stripTrailingBlanksStringBuf(sb);
|
|
|
|
|
1997-03-31 22:16:11 +08:00
|
|
|
switch (cur_part) {
|
|
|
|
case PREIN_PART:
|
|
|
|
t1 = RPMTAG_PREIN;
|
1997-07-07 22:51:54 +08:00
|
|
|
t2 = RPMTAG_PREINPROG;
|
1997-03-31 22:16:11 +08:00
|
|
|
break;
|
|
|
|
case POSTIN_PART:
|
|
|
|
t1 = RPMTAG_POSTIN;
|
1997-07-07 22:51:54 +08:00
|
|
|
t2 = RPMTAG_POSTINPROG;
|
1997-03-31 22:16:11 +08:00
|
|
|
break;
|
|
|
|
case PREUN_PART:
|
|
|
|
t1 = RPMTAG_PREUN;
|
1997-07-07 22:51:54 +08:00
|
|
|
t2 = RPMTAG_PREUNPROG;
|
1997-03-31 22:16:11 +08:00
|
|
|
break;
|
|
|
|
case POSTUN_PART:
|
|
|
|
t1 = RPMTAG_POSTUN;
|
1997-07-07 22:51:54 +08:00
|
|
|
t2 = RPMTAG_POSTUNPROG;
|
1997-03-31 22:16:11 +08:00
|
|
|
break;
|
|
|
|
case VERIFYSCRIPT_PART:
|
|
|
|
t1 = RPMTAG_VERIFYSCRIPT;
|
|
|
|
break;
|
|
|
|
case DESCRIPTION_PART:
|
|
|
|
t1 = RPMTAG_DESCRIPTION;
|
|
|
|
break;
|
|
|
|
case CHANGELOG_PART:
|
|
|
|
/* %changelog is a little special. It goes in the */
|
|
|
|
/* "main" package no matter where it appears, and it */
|
|
|
|
/* ends up in all the packages. */
|
|
|
|
if (addChangelog(spec->packages->header, sb)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
1997-05-02 01:26:56 +08:00
|
|
|
case TRIGGERIN_PART:
|
|
|
|
if (addTrigger(cur_package, RPMSENSE_TRIGGER_IN,
|
1997-03-31 22:16:11 +08:00
|
|
|
getStringBuf(sb), triggerArgs)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
1997-05-02 01:26:56 +08:00
|
|
|
case TRIGGERUN_PART:
|
|
|
|
if (addTrigger(cur_package, RPMSENSE_TRIGGER_UN,
|
1997-03-31 22:16:11 +08:00
|
|
|
getStringBuf(sb), triggerArgs)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
1997-07-08 05:13:26 +08:00
|
|
|
if (t1 && (*(getStringBuf(sb)) != '\0')) {
|
1997-03-31 22:16:11 +08:00
|
|
|
headerAddEntry(cur_package->header, t1,
|
|
|
|
RPM_STRING_TYPE, getStringBuf(sb), 1);
|
1997-07-08 05:13:26 +08:00
|
|
|
}
|
|
|
|
if (t2) {
|
|
|
|
addReqProv(cur_package, RPMSENSE_PREREQ, scriptProg, NULL);
|
|
|
|
headerAddEntry(cur_package->header, t2,
|
|
|
|
RPM_STRING_TYPE, scriptProg, 1);
|
1997-03-31 22:16:11 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1995-12-14 23:52:51 +08:00
|
|
|
/**********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Main specfile parsing routine */
|
|
|
|
/* */
|
|
|
|
/**********************************************************************/
|
|
|
|
|
1997-07-25 21:09:05 +08:00
|
|
|
Spec *parseSpec(FILE *f, char *specfile, char *buildRootOverride)
|
|
|
|
{
|
|
|
|
Spec *res;
|
|
|
|
Spec s;
|
|
|
|
char **archs = NULL;
|
|
|
|
char **arch;
|
1997-08-20 00:35:33 +08:00
|
|
|
int i, count;
|
1997-07-25 21:09:05 +08:00
|
|
|
|
|
|
|
s = parseSpecAux(f, specfile, buildRootOverride, &archs);
|
|
|
|
|
|
|
|
if (s) {
|
|
|
|
/* No BuildArchitectures field */
|
|
|
|
res = (Spec *) malloc(2 * sizeof(Spec));
|
|
|
|
res[0] = s;
|
|
|
|
res[1] = NULL;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! archs) {
|
|
|
|
/* Error */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We have a BuildArchitectures field */
|
1997-08-20 00:35:33 +08:00
|
|
|
count = 0;
|
|
|
|
while (archs[count]) {
|
|
|
|
count++;
|
1997-07-25 21:09:05 +08:00
|
|
|
}
|
1997-08-20 00:35:33 +08:00
|
|
|
res = (Spec *) malloc(count * sizeof(Spec));
|
1997-07-25 21:09:05 +08:00
|
|
|
|
|
|
|
i = 0;
|
|
|
|
arch = archs;
|
|
|
|
while (*arch) {
|
|
|
|
if (rpmMachineScore(RPM_MACHTABLE_BUILDARCH, *arch)) {
|
|
|
|
rewind(f);
|
|
|
|
rpmSetMachine(*arch, NULL);
|
|
|
|
res[i] = parseSpecAux(f, specfile, buildRootOverride, NULL);
|
|
|
|
if (! res[i]) {
|
|
|
|
/* Error */
|
|
|
|
freeSplitString(archs);
|
|
|
|
while (i) {
|
|
|
|
i--;
|
|
|
|
freeSpec(res[i]);
|
|
|
|
}
|
|
|
|
free(res);
|
|
|
|
return NULL;
|
|
|
|
}
|
1997-08-20 00:35:33 +08:00
|
|
|
headerAddEntry(res[i]->packages->header, RPMTAG_BUILDARCHS,
|
|
|
|
RPM_STRING_ARRAY_TYPE, archs, count);
|
1997-07-25 21:09:05 +08:00
|
|
|
res[i]->buildArch = strdup(*arch);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
arch++;
|
|
|
|
}
|
|
|
|
res[i] = NULL;
|
|
|
|
|
|
|
|
freeSplitString(archs);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
Spec parseSpecAux(FILE *f, char *specfile, char *buildRootOverride,
|
|
|
|
char ***buildArchs)
|
1995-11-28 06:31:21 +08:00
|
|
|
{
|
1995-12-18 22:56:49 +08:00
|
|
|
char buf[LINE_BUF_SIZE]; /* read buffer */
|
1996-01-08 15:03:21 +08:00
|
|
|
char buf2[LINE_BUF_SIZE];
|
1996-05-08 02:49:33 +08:00
|
|
|
char fileFile[LINE_BUF_SIZE];
|
1997-07-04 00:34:12 +08:00
|
|
|
char scriptProg[LINE_BUF_SIZE];
|
1996-11-15 01:36:01 +08:00
|
|
|
char triggerArgs[LINE_BUF_SIZE];
|
1995-12-18 22:56:49 +08:00
|
|
|
char *line; /* "parsed" read buffer */
|
|
|
|
|
1997-03-31 22:16:11 +08:00
|
|
|
int x, serial, tag, cur_part;
|
1995-12-14 23:52:51 +08:00
|
|
|
int lookupopts;
|
1995-12-13 23:57:59 +08:00
|
|
|
StringBuf sb;
|
1995-12-14 23:52:51 +08:00
|
|
|
char *s = NULL;
|
1996-05-08 02:49:33 +08:00
|
|
|
char *s1, *s2;
|
1996-07-15 00:06:35 +08:00
|
|
|
int gotBuildroot = 0;
|
1996-07-10 06:28:22 +08:00
|
|
|
int gotRoot = 0;
|
1997-03-31 22:16:11 +08:00
|
|
|
int versionMacroSet = 0;
|
|
|
|
int releaseMacroSet = 0;
|
1995-12-12 06:52:59 +08:00
|
|
|
|
1995-12-13 23:57:59 +08:00
|
|
|
struct PackageRec *cur_package = NULL;
|
1995-12-13 01:53:17 +08:00
|
|
|
Spec spec = (struct SpecRec *) malloc(sizeof(struct SpecRec));
|
1995-12-13 23:57:59 +08:00
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
spec->name = NULL;
|
1996-02-16 06:55:44 +08:00
|
|
|
spec->specfile = strdup(specfile);
|
1996-01-18 02:16:46 +08:00
|
|
|
spec->numSources = 0;
|
|
|
|
spec->numPatches = 0;
|
1995-12-28 00:50:50 +08:00
|
|
|
spec->sources = NULL;
|
1995-12-13 23:57:59 +08:00
|
|
|
spec->prep = newStringBuf();
|
|
|
|
spec->build = newStringBuf();
|
|
|
|
spec->install = newStringBuf();
|
1996-01-29 11:31:39 +08:00
|
|
|
spec->doc = newStringBuf();
|
1995-12-13 23:57:59 +08:00
|
|
|
spec->clean = newStringBuf();
|
|
|
|
spec->packages = NULL;
|
1996-06-28 01:22:18 +08:00
|
|
|
spec->noSource = NULL;
|
|
|
|
spec->noPatch = NULL;
|
|
|
|
spec->numNoSource = 0;
|
|
|
|
spec->numNoPatch = 0;
|
1996-07-15 00:06:35 +08:00
|
|
|
spec->buildroot = NULL;
|
1996-08-30 02:32:01 +08:00
|
|
|
spec->autoReqProv = 1;
|
1997-07-25 21:09:05 +08:00
|
|
|
spec->buildArch = NULL;
|
1995-11-28 06:31:21 +08:00
|
|
|
|
1995-12-13 23:57:59 +08:00
|
|
|
sb = newStringBuf();
|
|
|
|
reset_spec(); /* Reset the parser */
|
1996-01-29 11:31:39 +08:00
|
|
|
|
1997-07-07 22:51:54 +08:00
|
|
|
scriptProg[0] = '\0';
|
1995-12-13 23:57:59 +08:00
|
|
|
cur_part = PREAMBLE_PART;
|
1995-12-18 22:56:49 +08:00
|
|
|
while ((x = read_line(f, buf)) > 0) {
|
|
|
|
line = buf;
|
1995-12-14 23:52:51 +08:00
|
|
|
s = NULL;
|
1995-12-13 01:53:17 +08:00
|
|
|
if ((tag = check_part(line, &s))) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "Switching to part: %d\n", tag);
|
1997-03-31 22:16:11 +08:00
|
|
|
if (finishCurrentPart(spec, sb, cur_package,
|
1997-07-07 22:51:54 +08:00
|
|
|
cur_part, triggerArgs, scriptProg)) {
|
1997-03-31 22:16:11 +08:00
|
|
|
return NULL;
|
1995-12-13 23:57:59 +08:00
|
|
|
}
|
|
|
|
cur_part = tag;
|
|
|
|
truncStringBuf(sb);
|
1995-12-14 23:52:51 +08:00
|
|
|
|
|
|
|
/* Now switch the current package to s */
|
|
|
|
if (s) {
|
|
|
|
switch (tag) {
|
|
|
|
case PREP_PART:
|
|
|
|
case BUILD_PART:
|
|
|
|
case INSTALL_PART:
|
|
|
|
case CLEAN_PART:
|
1995-12-21 07:30:46 +08:00
|
|
|
case CHANGELOG_PART:
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADARG, "Tag takes no arguments: %s", s);
|
1995-12-18 22:56:49 +08:00
|
|
|
return NULL;
|
1995-12-14 23:52:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-05-08 02:49:33 +08:00
|
|
|
/* Rip through s for -f in %files */
|
1997-07-04 00:34:12 +08:00
|
|
|
/* not only is this code disgusting, but it allows -f on any tag */
|
1996-05-08 02:49:33 +08:00
|
|
|
fileFile[0] = '\0';
|
|
|
|
s1 = NULL;
|
|
|
|
if (s &&
|
|
|
|
((s1 = strstr(s, " -f ")) ||
|
|
|
|
(!strncmp(s, "-f ", 3)))) {
|
|
|
|
if (s1) {
|
|
|
|
s1[0] = ' ';
|
|
|
|
s1++;
|
|
|
|
} else {
|
|
|
|
s1 = s;
|
|
|
|
}
|
|
|
|
s1[0] = ' '; s1[1] = ' '; s1[2] = ' ';
|
|
|
|
s1 += 3;
|
|
|
|
while (isspace(*s1)) {
|
|
|
|
s1++;
|
|
|
|
}
|
1997-07-07 22:51:54 +08:00
|
|
|
|
1996-05-08 02:49:33 +08:00
|
|
|
s2 = fileFile;
|
|
|
|
while (*s1 && !isspace(*s1)) {
|
|
|
|
*s2 = *s1;
|
|
|
|
*s1 = ' ';
|
|
|
|
s1++;
|
|
|
|
s2++;
|
|
|
|
}
|
|
|
|
*s2 = '\0';
|
|
|
|
while (isspace(*s)) {
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
if (! *s) {
|
|
|
|
s = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "fileFile = %s\n",
|
1996-11-15 01:36:01 +08:00
|
|
|
fileFile[0] ? fileFile : "(null)");
|
|
|
|
|
|
|
|
/* If trigger, pull off the args */
|
1997-05-02 01:26:56 +08:00
|
|
|
if (tag == TRIGGERIN_PART || tag == TRIGGERUN_PART) {
|
1996-11-15 01:36:01 +08:00
|
|
|
s1 = strstr(s, "--");
|
|
|
|
if (s1) {
|
|
|
|
strcpy(triggerArgs, s1+2);
|
|
|
|
*s1 = '\0';
|
|
|
|
s = strtok(s, " \n\t");
|
|
|
|
} else {
|
|
|
|
strcpy(triggerArgs, s);
|
|
|
|
s = NULL;
|
|
|
|
}
|
|
|
|
}
|
1997-07-04 00:34:12 +08:00
|
|
|
|
1997-07-07 22:51:54 +08:00
|
|
|
/* find possible -p <prog> */
|
1997-07-04 00:34:12 +08:00
|
|
|
if ((tag == PREIN_PART) ||
|
|
|
|
(tag == POSTIN_PART) ||
|
|
|
|
(tag == PREUN_PART) ||
|
|
|
|
(tag == POSTUN_PART)) {
|
1997-07-07 22:51:54 +08:00
|
|
|
|
|
|
|
scriptProg[0] = '\0';
|
1997-07-04 00:34:12 +08:00
|
|
|
s1 = NULL;
|
1997-07-07 22:51:54 +08:00
|
|
|
|
1997-07-04 00:34:12 +08:00
|
|
|
if (s &&
|
|
|
|
((s1 = strstr(s, " -p ")) ||
|
|
|
|
(!strncmp(s, "-p ", 3)))) {
|
1997-07-07 22:51:54 +08:00
|
|
|
|
|
|
|
if (s1) {
|
|
|
|
s1[0] = ' ';
|
|
|
|
s1++;
|
|
|
|
} else {
|
|
|
|
s1 = s;
|
|
|
|
}
|
|
|
|
s1[0] = ' '; s1[1] = ' '; s1[2] = ' ';
|
|
|
|
s1 += 3;
|
|
|
|
while (isspace(*s1)) {
|
|
|
|
s1++;
|
|
|
|
}
|
|
|
|
|
|
|
|
s2 = scriptProg;
|
|
|
|
while (*s1 && !isspace(*s1)) {
|
|
|
|
*s2 = *s1;
|
|
|
|
*s1 = ' ';
|
|
|
|
s1++;
|
|
|
|
s2++;
|
|
|
|
}
|
1997-07-04 00:34:12 +08:00
|
|
|
|
1997-07-07 22:51:54 +08:00
|
|
|
*s2 = '\0';
|
|
|
|
while (isspace(*s)) {
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
if (! *s) {
|
|
|
|
s = NULL;
|
|
|
|
}
|
1997-07-04 00:34:12 +08:00
|
|
|
}
|
|
|
|
|
1997-07-07 22:51:54 +08:00
|
|
|
/* defaults to /bin/sh */
|
|
|
|
if (! scriptProg[0]) {
|
|
|
|
strcpy(scriptProg, "/bin/sh");
|
|
|
|
} else {
|
|
|
|
if (scriptProg[0] != '/') {
|
|
|
|
rpmError(RPMERR_BADSPEC, "pre/post -p arg must begin with \'/\': %s", scriptProg);
|
|
|
|
return NULL;
|
|
|
|
}
|
1997-07-04 00:34:12 +08:00
|
|
|
}
|
1997-07-07 22:51:54 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "scriptProg = %s\n", scriptProg);
|
1997-07-04 00:34:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* At this point s is the remaining args, which can only */
|
|
|
|
/* be -n <pkg>, or simply <pkg>. */
|
1996-05-08 02:49:33 +08:00
|
|
|
|
1995-12-21 07:30:46 +08:00
|
|
|
/* Handle -n in part tags */
|
|
|
|
lookupopts = 0;
|
|
|
|
if (s) {
|
|
|
|
if (!strncmp(s, "-n", 2)) {
|
|
|
|
s += 2;
|
|
|
|
s += strspn(s, ": \t");
|
|
|
|
if (*s == '\0') {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADARG, "-n takes argument");
|
1995-12-21 07:30:46 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
lookupopts = LP_NEWNAME;
|
|
|
|
} else {
|
|
|
|
lookupopts = LP_SUBNAME;
|
|
|
|
}
|
1996-02-16 13:55:17 +08:00
|
|
|
/* Handle trailing whitespace */
|
|
|
|
s1 = s + strlen(s) - 1;
|
|
|
|
while (*s1 == ' ' || *s1 == '\n' || *s1 == '\t') {
|
|
|
|
s1--;
|
|
|
|
}
|
|
|
|
s1++;
|
|
|
|
*s1 = '\0';
|
1995-12-21 07:30:46 +08:00
|
|
|
}
|
1996-05-08 02:49:33 +08:00
|
|
|
|
1996-02-16 13:55:17 +08:00
|
|
|
switch (tag) {
|
|
|
|
case PREP_PART:
|
|
|
|
case BUILD_PART:
|
|
|
|
case INSTALL_PART:
|
|
|
|
case CLEAN_PART:
|
|
|
|
case CHANGELOG_PART:
|
|
|
|
/* Do not switch parts for these */
|
|
|
|
break;
|
|
|
|
case PREAMBLE_PART:
|
|
|
|
lookupopts |= LP_CREATE | LP_FAIL_EXISTS;
|
|
|
|
/* Fall through */
|
|
|
|
default:
|
|
|
|
/* XXX - should be able to drop the -n in non-%package parts */
|
|
|
|
if (! lookup_package(spec, &cur_package, s, lookupopts)) {
|
1997-02-18 09:47:16 +08:00
|
|
|
rpmError(RPMERR_INTERNAL, "Package lookup failed: %s",
|
|
|
|
(s) ? s : "(main)");
|
1996-02-16 13:55:17 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "Switched to package: %s\n",
|
1996-11-07 04:58:54 +08:00
|
|
|
s ? s : "(main)");
|
1995-12-14 23:52:51 +08:00
|
|
|
}
|
|
|
|
|
1995-12-20 01:56:45 +08:00
|
|
|
if (cur_part == FILES_PART) {
|
1995-12-21 07:30:46 +08:00
|
|
|
/* set files to 0 (current -1 means no %files, no package */
|
1995-12-20 01:56:45 +08:00
|
|
|
cur_package->files = 0;
|
1996-05-08 02:49:33 +08:00
|
|
|
if (fileFile[0]) {
|
|
|
|
cur_package->fileFile = strdup(fileFile);
|
|
|
|
}
|
1995-12-20 01:56:45 +08:00
|
|
|
}
|
1996-11-15 01:36:01 +08:00
|
|
|
|
|
|
|
/* This line has no content -- it was just a control line */
|
1995-12-13 01:53:17 +08:00
|
|
|
continue;
|
|
|
|
}
|
1995-12-14 23:52:51 +08:00
|
|
|
|
1996-02-16 13:55:17 +08:00
|
|
|
/* Check for implicit "base" package. */
|
|
|
|
/* That means that the specfile does not start with %package */
|
1995-12-14 23:52:51 +08:00
|
|
|
if (! cur_package) {
|
|
|
|
lookupopts = 0;
|
|
|
|
if (cur_part == PREAMBLE_PART) {
|
|
|
|
lookupopts = LP_CREATE | LP_FAIL_EXISTS;
|
|
|
|
}
|
|
|
|
if (! lookup_package(spec, &cur_package, NULL, lookupopts)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_INTERNAL, "Base package lookup failed!");
|
1995-12-18 22:56:49 +08:00
|
|
|
return NULL;
|
1995-12-14 23:52:51 +08:00
|
|
|
}
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "Switched to BASE package\n");
|
1995-12-14 23:52:51 +08:00
|
|
|
}
|
1997-07-04 00:34:12 +08:00
|
|
|
|
|
|
|
switch (cur_part) {
|
1995-12-13 01:53:17 +08:00
|
|
|
case PREAMBLE_PART:
|
|
|
|
if ((tag = find_preamble_line(line, &s))) {
|
|
|
|
switch (tag) {
|
1996-01-08 15:03:21 +08:00
|
|
|
case RPMTAG_EXCLUDE:
|
|
|
|
case RPMTAG_EXCLUSIVE:
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_WARNING,
|
1996-07-17 09:35:08 +08:00
|
|
|
"Exclude/Exclusive are depricated.\n"
|
|
|
|
"Use ExcludeArch/ExclusiveArch instead.\n");
|
1996-01-08 15:03:21 +08:00
|
|
|
sprintf(buf2, "%s %s",
|
|
|
|
(tag == RPMTAG_EXCLUDE) ? "%ifarch" : "%ifnarch",
|
|
|
|
s);
|
|
|
|
if (match_arch(buf2)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADARCH, "Arch mismatch!");
|
1996-01-08 15:03:21 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-07-17 09:35:08 +08:00
|
|
|
addListEntry(cur_package->header,
|
|
|
|
(tag == RPMTAG_EXCLUDE) ?
|
|
|
|
RPMTAG_EXCLUDEARCH : RPMTAG_EXCLUSIVEARCH,
|
|
|
|
s);
|
1996-01-08 15:03:21 +08:00
|
|
|
break;
|
1996-07-17 09:35:08 +08:00
|
|
|
case RPMTAG_EXCLUDEARCH:
|
|
|
|
case RPMTAG_EXCLUSIVEARCH:
|
|
|
|
sprintf(buf2, "%s %s", (tag == RPMTAG_EXCLUDEARCH) ?
|
|
|
|
"%ifarch" : "%ifnarch", s);
|
|
|
|
if (match_arch(buf2)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADARCH, "Arch mismatch!");
|
1996-07-17 09:35:08 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
addListEntry(cur_package->header, tag, s);
|
|
|
|
break;
|
|
|
|
case RPMTAG_EXCLUDEOS:
|
|
|
|
case RPMTAG_EXCLUSIVEOS:
|
|
|
|
sprintf(buf2, "%s %s", (tag == RPMTAG_EXCLUDEOS) ?
|
|
|
|
"%ifos" : "%ifnos", s);
|
1996-07-21 05:09:00 +08:00
|
|
|
if (match_os(buf2)) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADOS, "OS mismatch!");
|
1996-07-17 09:35:08 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
addListEntry(cur_package->header, tag, s);
|
|
|
|
break;
|
1995-12-13 01:53:17 +08:00
|
|
|
case RPMTAG_NAME:
|
1996-02-23 03:21:54 +08:00
|
|
|
s1 = s;
|
|
|
|
while (*s1 && *s1 != ' ' && *s1 != '\t') s1++;
|
|
|
|
*s1 = '\0';
|
1995-12-14 23:52:51 +08:00
|
|
|
if (!spec->name) {
|
|
|
|
spec->name = strdup(s);
|
|
|
|
}
|
1996-02-22 01:19:52 +08:00
|
|
|
/* The NAME entries must be generated after */
|
|
|
|
/* the whole spec file is parsed. */
|
|
|
|
break;
|
1995-12-13 01:53:17 +08:00
|
|
|
case RPMTAG_VERSION:
|
|
|
|
case RPMTAG_RELEASE:
|
1996-02-23 03:21:54 +08:00
|
|
|
s1 = s;
|
|
|
|
while (*s1 && *s1 != ' ' && *s1 != '\t') s1++;
|
|
|
|
*s1 = '\0';
|
1997-06-04 06:02:37 +08:00
|
|
|
if (s1 == s) {
|
|
|
|
rpmError(RPMERR_BADSPEC, (tag == RPMTAG_VERSION) ?
|
|
|
|
"Empty version field." :
|
|
|
|
"Empty release field.");
|
|
|
|
return NULL;
|
|
|
|
}
|
1997-03-31 22:16:11 +08:00
|
|
|
if (tag == RPMTAG_VERSION) {
|
|
|
|
if (! versionMacroSet) {
|
|
|
|
versionMacroSet = 1;
|
|
|
|
addMacro("PACKAGE_VERSION", s);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (! releaseMacroSet) {
|
|
|
|
releaseMacroSet = 1;
|
|
|
|
addMacro("PACKAGE_RELEASE", s);
|
|
|
|
}
|
|
|
|
}
|
1996-07-08 23:46:29 +08:00
|
|
|
case RPMTAG_SUMMARY:
|
1995-12-13 01:53:17 +08:00
|
|
|
case RPMTAG_DISTRIBUTION:
|
|
|
|
case RPMTAG_VENDOR:
|
|
|
|
case RPMTAG_COPYRIGHT:
|
|
|
|
case RPMTAG_PACKAGER:
|
|
|
|
case RPMTAG_GROUP:
|
|
|
|
case RPMTAG_URL:
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(cur_package->header, tag, RPM_STRING_TYPE, s, 1);
|
1995-12-13 01:53:17 +08:00
|
|
|
break;
|
1997-07-25 21:09:05 +08:00
|
|
|
case RPMTAG_BUILDARCHS:
|
|
|
|
if (buildArchs) {
|
|
|
|
*buildArchs = splitString(s, strlen(s), ' ');
|
|
|
|
freeSpec(spec);
|
|
|
|
freeStringBuf(sb);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
1996-07-15 00:06:35 +08:00
|
|
|
case RPMTAG_BUILDROOT:
|
|
|
|
gotBuildroot = 1;
|
|
|
|
spec->buildroot = strdup(s);
|
1996-07-10 06:28:22 +08:00
|
|
|
break;
|
1996-07-09 10:06:26 +08:00
|
|
|
case RPMTAG_DEFAULTPREFIX:
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(cur_package->header, tag, RPM_STRING_TYPE, s, 1);
|
1996-07-09 10:06:26 +08:00
|
|
|
break;
|
1996-02-20 01:03:29 +08:00
|
|
|
case RPMTAG_SERIAL:
|
|
|
|
serial = atoi(s);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(cur_package->header, tag, RPM_INT32_TYPE, &serial, 1);
|
1996-02-20 01:03:29 +08:00
|
|
|
break;
|
1996-01-12 15:31:04 +08:00
|
|
|
case RPMTAG_DESCRIPTION:
|
|
|
|
/* Special case -- need to handle backslash */
|
|
|
|
truncStringBuf(sb);
|
|
|
|
while (1) {
|
|
|
|
s1 = s + strlen(s) - 1;
|
|
|
|
if (*s1 != '\\') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*s1 = '\0';
|
|
|
|
appendLineStringBuf(sb, s);
|
|
|
|
read_line(f, buf);
|
|
|
|
s = buf;
|
|
|
|
}
|
|
|
|
appendStringBuf(sb, s);
|
1996-11-19 02:02:36 +08:00
|
|
|
headerAddEntry(cur_package->header, RPMTAG_DESCRIPTION,
|
|
|
|
RPM_STRING_TYPE, getStringBuf(sb), 1);
|
1996-01-12 15:31:04 +08:00
|
|
|
break;
|
1995-12-28 00:50:50 +08:00
|
|
|
case RPMTAG_ROOT:
|
1996-07-10 06:28:22 +08:00
|
|
|
/* special case */
|
|
|
|
gotRoot = 1;
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "Got root: %s\n", s);
|
|
|
|
rpmMessage(RPMMESS_WARNING, "The Root: tag is depricated. Use Buildroot: instead\n");
|
|
|
|
rpmSetVar(RPMVAR_ROOT, s);
|
1996-07-10 06:28:22 +08:00
|
|
|
break;
|
1996-01-08 15:03:21 +08:00
|
|
|
case RPMTAG_ICON:
|
|
|
|
cur_package->icon = strdup(s);
|
|
|
|
break;
|
1996-06-28 01:22:18 +08:00
|
|
|
case RPMTAG_NOPATCH:
|
|
|
|
case RPMTAG_NOSOURCE:
|
|
|
|
if (noSourcePatch(spec, s, tag)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
1995-12-28 00:50:50 +08:00
|
|
|
case RPMTAG_SOURCE:
|
|
|
|
case RPMTAG_PATCH:
|
|
|
|
if (addSource(spec, line)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
1996-05-02 08:48:18 +08:00
|
|
|
case RPMTAG_PROVIDES:
|
1996-05-08 02:49:33 +08:00
|
|
|
if (parseProvides(cur_package, s)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case RPMTAG_REQUIREFLAGS:
|
1996-06-28 04:15:53 +08:00
|
|
|
case RPMTAG_CONFLICTFLAGS:
|
1997-06-20 03:46:19 +08:00
|
|
|
case RPMTAG_PREREQ:
|
1997-09-17 03:20:16 +08:00
|
|
|
case RPMTAG_OBSOLETES:
|
1996-06-28 04:15:53 +08:00
|
|
|
if (parseRequiresConflicts(cur_package, s, tag)) {
|
1996-05-08 02:49:33 +08:00
|
|
|
return NULL;
|
1996-05-02 08:48:18 +08:00
|
|
|
}
|
|
|
|
break;
|
1996-08-30 02:32:01 +08:00
|
|
|
case RPMTAG_AUTOREQPROV:
|
|
|
|
s1 = strtok(s, " \t\n");
|
|
|
|
if (!s1) {
|
|
|
|
spec->autoReqProv = 0;
|
|
|
|
} else if (s1[0] == 'n' || s1[0] == 'N') {
|
|
|
|
spec->autoReqProv = 0;
|
|
|
|
} else if (!strcasecmp(s1, "false")) {
|
|
|
|
spec->autoReqProv = 0;
|
|
|
|
} else if (!strcasecmp(s1, "off")) {
|
|
|
|
spec->autoReqProv = 0;
|
|
|
|
} else if (!strcmp(s1, "0")) {
|
|
|
|
spec->autoReqProv = 0;
|
|
|
|
}
|
|
|
|
break;
|
1995-12-13 01:53:17 +08:00
|
|
|
default:
|
1996-11-19 02:02:36 +08:00
|
|
|
/* rpmMessage(RPMMESS_DEBUG, "Skipping: %s\n", line); */
|
1996-02-23 04:01:56 +08:00
|
|
|
/* This shouldn't happen? */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_INTERNAL, "Bogus token");
|
1996-02-23 04:01:56 +08:00
|
|
|
return NULL;
|
1995-12-13 01:53:17 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Not a recognized preamble part */
|
1996-02-23 04:01:56 +08:00
|
|
|
s1 = line;
|
1996-06-03 02:06:00 +08:00
|
|
|
while (*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
|
|
|
|
/* Handle blanks lines and comments */
|
|
|
|
if (*s1 && (*s1 != '#')) {
|
1996-11-19 02:02:36 +08:00
|
|
|
/*rpmMessage(RPMMESS_WARNING, "Unknown Field: %s\n", line);*/
|
|
|
|
rpmError(RPMERR_BADSPEC, "Unknown Field: %s\n", line);
|
1996-05-02 08:48:18 +08:00
|
|
|
return NULL;
|
1996-02-23 04:01:56 +08:00
|
|
|
}
|
1995-12-13 01:53:17 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PREP_PART:
|
1995-12-13 23:57:59 +08:00
|
|
|
appendLineStringBuf(spec->prep, line);
|
|
|
|
break;
|
1995-12-13 01:53:17 +08:00
|
|
|
case BUILD_PART:
|
1995-12-13 23:57:59 +08:00
|
|
|
appendLineStringBuf(spec->build, line);
|
|
|
|
break;
|
1995-12-13 01:53:17 +08:00
|
|
|
case INSTALL_PART:
|
1995-12-13 23:57:59 +08:00
|
|
|
appendLineStringBuf(spec->install, line);
|
|
|
|
break;
|
1995-12-13 01:53:17 +08:00
|
|
|
case CLEAN_PART:
|
1995-12-13 23:57:59 +08:00
|
|
|
appendLineStringBuf(spec->clean, line);
|
1995-12-13 01:53:17 +08:00
|
|
|
break;
|
1996-07-03 03:16:46 +08:00
|
|
|
case DESCRIPTION_PART:
|
1995-12-21 07:30:46 +08:00
|
|
|
case CHANGELOG_PART:
|
1995-12-13 01:53:17 +08:00
|
|
|
case PREIN_PART:
|
|
|
|
case POSTIN_PART:
|
|
|
|
case PREUN_PART:
|
|
|
|
case POSTUN_PART:
|
1996-11-15 05:57:24 +08:00
|
|
|
case VERIFYSCRIPT_PART:
|
1995-12-13 23:57:59 +08:00
|
|
|
appendLineStringBuf(sb, line);
|
1995-12-13 01:53:17 +08:00
|
|
|
break;
|
1997-05-02 01:26:56 +08:00
|
|
|
case TRIGGERIN_PART:
|
|
|
|
case TRIGGERUN_PART:
|
1996-11-15 01:36:01 +08:00
|
|
|
appendLineStringBuf(sb, line);
|
|
|
|
break;
|
1995-12-13 01:53:17 +08:00
|
|
|
case FILES_PART:
|
1996-06-25 06:04:49 +08:00
|
|
|
s1 = line;
|
|
|
|
while (*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
|
|
|
|
/* Handle blanks lines and comments */
|
|
|
|
if (*s1 && (*s1 != '#')) {
|
|
|
|
cur_package->files++;
|
|
|
|
appendLineStringBuf(cur_package->filelist, line);
|
|
|
|
}
|
1995-12-13 01:53:17 +08:00
|
|
|
break;
|
|
|
|
default:
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_INTERNAL, "Bad part");
|
1995-12-18 22:56:49 +08:00
|
|
|
return NULL;
|
1995-12-14 23:52:51 +08:00
|
|
|
} /* switch */
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
|
|
|
if (x < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
1995-12-13 23:57:59 +08:00
|
|
|
|
1997-03-31 22:16:11 +08:00
|
|
|
/* finish current part */
|
|
|
|
if (finishCurrentPart(spec, sb, cur_package,
|
1997-07-07 22:51:54 +08:00
|
|
|
cur_part, triggerArgs,
|
|
|
|
scriptProg)) {
|
1997-03-31 22:16:11 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
1997-07-25 21:09:05 +08:00
|
|
|
|
|
|
|
freeStringBuf(sb);
|
1997-03-31 22:16:11 +08:00
|
|
|
|
1996-07-15 00:06:35 +08:00
|
|
|
if (gotRoot && gotBuildroot) {
|
1996-07-10 06:28:22 +08:00
|
|
|
freeSpec(spec);
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADSPEC,
|
1996-07-15 00:06:35 +08:00
|
|
|
"Spec file can not have both Root: and Buildroot:");
|
1996-07-10 06:28:22 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
1996-07-15 00:06:35 +08:00
|
|
|
if (spec->buildroot) {
|
1996-07-15 00:38:57 +08:00
|
|
|
/* This package can do build roots */
|
1996-07-15 00:06:35 +08:00
|
|
|
if (buildRootOverride) {
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmSetVar(RPMVAR_ROOT, buildRootOverride);
|
|
|
|
rpmSetVar(RPMVAR_BUILDROOT, buildRootOverride);
|
1996-07-10 06:28:22 +08:00
|
|
|
} else {
|
1996-11-19 02:02:36 +08:00
|
|
|
if ((s = rpmGetVar(RPMVAR_BUILDROOT))) {
|
1996-07-10 06:28:22 +08:00
|
|
|
/* Take build prefix from rpmrc */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmSetVar(RPMVAR_ROOT, s);
|
1996-07-10 06:28:22 +08:00
|
|
|
} else {
|
|
|
|
/* Use default */
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmSetVar(RPMVAR_ROOT, spec->buildroot);
|
|
|
|
rpmSetVar(RPMVAR_BUILDROOT, spec->buildroot);
|
1996-07-10 06:28:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Package can not do build prefixes */
|
1996-07-15 00:06:35 +08:00
|
|
|
if (buildRootOverride) {
|
1996-07-10 06:28:22 +08:00
|
|
|
freeSpec(spec);
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmError(RPMERR_BADARG, "Package can not do build prefixes");
|
1996-07-10 06:28:22 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-04-15 04:05:43 +08:00
|
|
|
generateNames(spec);
|
1995-12-13 01:53:17 +08:00
|
|
|
return spec;
|
|
|
|
}
|
|
|
|
|
1995-12-14 23:52:51 +08:00
|
|
|
/**********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Resets the parser */
|
|
|
|
/* */
|
|
|
|
/**********************************************************************/
|
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
static void reset_spec()
|
|
|
|
{
|
|
|
|
static done = 0;
|
|
|
|
struct read_level_entry *rl;
|
|
|
|
struct preamble_line *p = preamble_spec;
|
|
|
|
struct part_rec *p1 = part_list;
|
|
|
|
|
1996-11-19 02:02:36 +08:00
|
|
|
rpmSetVar(RPMVAR_ROOT, NULL);
|
1996-02-22 10:49:12 +08:00
|
|
|
|
1995-12-13 01:53:17 +08:00
|
|
|
while (read_level) {
|
|
|
|
rl = read_level;
|
|
|
|
read_level = read_level->next;
|
|
|
|
free(rl);
|
|
|
|
}
|
|
|
|
read_level = malloc(sizeof(struct read_level_entry));
|
|
|
|
read_level->next = NULL;
|
|
|
|
read_level->reading = 1;
|
1997-03-31 22:16:11 +08:00
|
|
|
|
|
|
|
resetMacros();
|
1995-12-13 01:53:17 +08:00
|
|
|
|
|
|
|
if (! done) {
|
|
|
|
/* Put one time only things in here */
|
|
|
|
while (p->tag) {
|
|
|
|
p->len = strlen(p->token);
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
while (p1->part) {
|
|
|
|
p1->len = strlen(p1->s);
|
|
|
|
p1++;
|
|
|
|
}
|
|
|
|
|
|
|
|
done = 1;
|
|
|
|
}
|
1995-11-28 06:31:21 +08:00
|
|
|
}
|
1995-12-18 22:56:49 +08:00
|
|
|
|
|
|
|
/**********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Spec struct dumping (for debugging) */
|
|
|
|
/* */
|
|
|
|
/**********************************************************************/
|
|
|
|
|
|
|
|
void dumpSpec(Spec s, FILE *f)
|
|
|
|
{
|
|
|
|
struct PackageRec *p;
|
|
|
|
|
|
|
|
fprintf(f, "########################################################\n");
|
|
|
|
fprintf(f, "SPEC NAME = (%s)\n", s->name);
|
|
|
|
fprintf(f, "PREP =v\n");
|
|
|
|
fprintf(f, "%s", getStringBuf(s->prep));
|
|
|
|
fprintf(f, "PREP =^\n");
|
|
|
|
fprintf(f, "BUILD =v\n");
|
|
|
|
fprintf(f, "%s", getStringBuf(s->build));
|
|
|
|
fprintf(f, "BUILD =^\n");
|
|
|
|
fprintf(f, "INSTALL =v\n");
|
|
|
|
fprintf(f, "%s", getStringBuf(s->install));
|
|
|
|
fprintf(f, "INSTALL =^\n");
|
|
|
|
fprintf(f, "CLEAN =v\n");
|
|
|
|
fprintf(f, "%s", getStringBuf(s->clean));
|
|
|
|
fprintf(f, "CLEAN =^\n");
|
|
|
|
|
|
|
|
p = s->packages;
|
|
|
|
while (p) {
|
|
|
|
dumpPackage(p, f);
|
|
|
|
p = p->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dumpPackage(struct PackageRec *p, FILE *f)
|
|
|
|
{
|
|
|
|
fprintf(f, "_________________________________________________________\n");
|
|
|
|
fprintf(f, "SUBNAME = (%s)\n", p->subname);
|
|
|
|
fprintf(f, "NEWNAME = (%s)\n", p->newname);
|
|
|
|
fprintf(f, "FILES = %d\n", p->files);
|
|
|
|
fprintf(f, "FILES =v\n");
|
|
|
|
fprintf(f, "%s", getStringBuf(p->filelist));
|
|
|
|
fprintf(f, "FILES =^\n");
|
|
|
|
fprintf(f, "HEADER =v\n");
|
1997-01-23 04:41:50 +08:00
|
|
|
headerDump(p->header, f, 1, rpmTagTable);
|
1995-12-18 22:56:49 +08:00
|
|
|
fprintf(f, "HEADER =^\n");
|
|
|
|
|
|
|
|
}
|