merged in Marc's new build code

CVS patchset: 1956
CVS date: 1998/01/12 21:31:29
This commit is contained in:
ewt 1998-01-12 21:31:29 +00:00
parent ec07f9df95
commit 757e50ffc8
49 changed files with 5325 additions and 4969 deletions

31
CHANGES
View File

@ -1,5 +1,36 @@
2.4.11 -> 2.5:
- added many more i18n strings
- merged in large rewrite of build code, which includes the following
changes:
- all scripts can now take -p <prog>
- all scripts can now take -p "<prog> <arg>..."
- more strict about %package placement and use of main package
preamble
- %attr(mode, user, group [, dirmode])
- %defattr()
- %defverify()
- Root: is depricated. Use BuildRoot: instead
- "nosrc" sources arn't deleted when sources are removed
- New tag DocDir: <dir> to set alternate doc dir (default is
/usr/doc)
- %doc should work as expected with buildroot, prefix, DocDir:
- all file processing is done before any packaging
- should work with modern patch programs (later than 2.1)
- %patch -z <arg> same as %patch -b <arg>
- %define only defines a macro if it starts a line
- script prog entries are now arrays (ie with arguments)
- standard macros: tag names, buildarch, buildos, buildarch_lc,
buildos_lc, PATCHn, SOURCEn, PATCHURLn, SOURCEURLn, sourcedir,
builddir, optflags
- deprecate require_distribution, require_icon, require_vendor
- add RPMTAG_FILEDEVICES and RPMTAG_FILEINODES to header
- export variables in scripts
- fixed tag:field bug
- %lang() in %files
- %description -l <lang>
- Summary(<lang>):
- fixed read_line() termination usage
- Makefile changes to shorten compiler lines
2.4.11 -> 2.4.12:
- intialize reserved portion of lead when writing packages

View File

@ -33,10 +33,11 @@ ETCDIR=$(ROOT)/etc
SUBDIRS = popt @MISCDIR@ lib build tools @PO@
INSTSUBDIRS = lib @PO@
OTHERSUBDIRS = docs autodeps
OBJS = rpm.o query.o install.o verify.o checksig.o ftp.o url.o @GETTEXTSTUB@
OBJS = rpm.o query.o install.o verify.o checksig.o ftp.o url.o build.o \
@GETTEXTSTUB@
PROGS = @RPM@ rpm2cpio
LIBS = @LIBS@ @LIBINTL@ @LIBDL@
LOADLIBES = -lbuild popt/libpopt.a $(topdir)/lib/librpm.a -L$(topdir)/misc @LIBMISC@
LOADLIBES = -lrpmbuild -lpopt -lrpm @LIBMISC@
SOURCES = $(subst .o,.c,$(OBJS))
@ -48,11 +49,11 @@ endif
all: $(TARGET)
rpm: lib/librpm.a build/libbuild.a @MISCPATH@ $(OBJS)
$(CC) -o rpm -static $(LDFLAGS) $(OBJS) $(LOADLIBES) $(LIBS) \
rpm: lib/librpm.a build/librpmbuild.a @MISCPATH@ $(OBJS)
$(CC) -o rpm -static $(OBJS) $(LDFLAGS) $(LOADLIBES) $(LIBS) \
$(LIBEFENCE)
rpm.shared: lib/librpm.a build/libbuild.a $(OBJS)
rpm.shared: lib/librpm.a build/rpmlibbuild.a $(OBJS)
$(CC) -o rpm.shared $(LDFLAGS) $(OBJS) $(LOADLIBES) $(LIBS) \
$(LIBEFENCE)
@ -68,6 +69,8 @@ rpm2cpio: lib/librpm.a rpm2cpio.o
rpm.o: rpm.c query.h install.h lib/rpmlib.h Makefile
$(CC) $(CFLAGS) -DRPMNLSPACKAGE=\"$(RPMNLSPACKAGE)\" \
-DRPMNLSDIR=\"$(RPMNLSDIR)\" \
-DVERSION=\"$(VERSION)\" \
-DLIBRPMALIAS_FILENAME="\"$(LIBRPMALIAS_FILENAME)"\" \
-c $(srcdir)/rpm.c
# these rules should be in here, but they drive me batty

View File

@ -12,12 +12,8 @@ LIBRPMALIAS_FILENAME=$(libdir)/rpmpopt
RPMNLSDIR=@datadir@/locale
RPMNLSPACKAGE=rpm
CFLAGS = @CFLAGS@ @INCPATH@ $(WARNINGS) $(OPTS) -I$(topdir) \
-I$(topdir)/lib -I$(topdir)/misc -Wall -Wstrict-prototypes \
-DLIBRPMRC_FILENAME="\"$(LIBRPMRC_FILENAME)"\" \
-DLIBRPMALIAS_FILENAME="\"$(LIBRPMALIAS_FILENAME)"\" \
-DVERSION=\"$(VERSION)\"
LDFLAGS = @LDFLAGS@ -Llib -Lbuild -Lmisc -L$(topdir)/lib \
-L$(topdir)/build -L$(topdir)/misc
VERSION = 2.4.12
-I$(topdir)/lib -I$(topdir)/misc -Wall -Wstrict-prototypes
LDFLAGS = @LDFLAGS@ -L$(topdir)/lib -L$(topdir)/build -L$(topdir)/misc
VERSION = 2.4.99
CC = @CC@

132
build.c Normal file
View File

@ -0,0 +1,132 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "build.h"
#include "intl.h"
#include "lib/rpmlib.h"
#include "build/build.h"
#include "build/parse.h"
#include "build/spec.h"
int build(char *arg, int buildAmount, char *passPhrase,
char *buildRoot, int fromTarball, int test, char *cookie) {
FILE *f;
char * specfile;
int res = 0;
struct stat statbuf;
char * specDir;
char * tmpSpecFile;
char * cmd;
char * s;
int count, fd;
char buf[BUFSIZ];
Spec spec = NULL;
if (fromTarball) {
specDir = rpmGetVar(RPMVAR_SPECDIR);
tmpSpecFile = alloca(BUFSIZ);
sprintf(tmpSpecFile, "%s/rpm-spec-file-%d", specDir, (int) getpid());
cmd = alloca(strlen(arg) + 50 + strlen(tmpSpecFile));
sprintf(cmd, "gunzip < %s | tar xOvf - \\*.spec 2>&1 > %s", arg,
tmpSpecFile);
if (!(f = popen(cmd, "r"))) {
fprintf(stderr, _("Failed to open tar pipe: %s\n"),
strerror(errno));
return 1;
}
if (!fgets(buf, sizeof(buf) - 1, f)) {
fprintf(stderr, _("Failed to read spec file from %s\n"), arg);
unlink(tmpSpecFile);
return 1;
}
pclose(f);
cmd = specfile = buf;
while (*cmd) {
if (*cmd == '/') specfile = cmd + 1;
cmd++;
}
cmd = specfile;
/* remove trailing \n */
specfile = cmd + strlen(cmd) - 1;
*specfile = '\0';
specfile = alloca(strlen(specDir) + strlen(cmd) + 5);
sprintf(specfile, "%s/%s", specDir, cmd);
if (rename(tmpSpecFile, specfile)) {
fprintf(stderr, _("Failed to rename %s to %s: %s\n"),
tmpSpecFile, specfile, strerror(errno));
unlink(tmpSpecFile);
return 1;
}
/* Make the directory which contains the tarball the source
directory for this run */
if (*arg != '/') {
getcwd(buf, BUFSIZ);
strcat(buf, "/");
strcat(buf, arg);
} else
strcpy(buf, arg);
cmd = buf + strlen(buf) - 1;
while (*cmd != '/') cmd--;
*cmd = '\0';
rpmSetVar(RPMVAR_SOURCEDIR, buf);
} else if (arg[0] == '/') {
specfile = arg;
} else {
specfile = alloca(BUFSIZ);
getcwd(specfile, BUFSIZ);
strcat(specfile, "/");
strcat(specfile, arg);
}
stat(specfile, &statbuf);
if (! S_ISREG(statbuf.st_mode)) {
fprintf(stderr, _("File is not a regular file: %s\n"), specfile);
return 1;
}
if (!(fd = open(specfile, O_RDONLY))) {
fprintf(stderr, _("Unable to open spec file: %s\n"), specfile);
return 1;
}
count = read(fd, buf, sizeof(buf));
close(fd);
s = buf;
while(count--) {
if (! (isprint(*s) || isspace(*s))) {
fprintf(stderr, _("File contains non-printable characters(%c): %s\n"), *s,
specfile);
return 1;
}
s++;
}
if (parseSpec(&spec, specfile, buildRoot, 0, passPhrase, cookie)) {
return 1;
}
if (buildSpec(spec, buildAmount, test)) {
freeSpec(spec);
return 1;
}
if (fromTarball) unlink(specfile);
freeSpec(spec);
return res;
}

7
build.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef H_BUILD
#define H_BUILD
int build(char *arg, int buildAmount, char *passPhrase,
char *buildRoot, int fromTarball, int test, char *cookie);
#endif

View File

@ -1,10 +1,16 @@
srcdir = @srcdir@
VPATH = $(srcdir)
LIBOBJECTS = spec.o vspec.o build.o files.o names.o pack.o myftw.o \
reqprov.o trigger.o macro.o
LIBBUILD = libbuild.a
LOADLIBES = -lrpm $(LIBEFENCE)
LIBOBJECTS = \
misc.o parsePreamble.o part.o \
package.o parseDescription.o parsePrep.o read.o \
parseFiles.o parseReqs.o reqprov.o \
parseChangelog.o parseSpec.o spec.o \
parseScript.o parseBuildInstallClean.o build.o \
files.o myftw.o names.o pack.o macro.o
LIBBUILD = librpmbuild.a
LOADLIBES = -lrpm -lz ../popt/libpopt.a $(LIBEFENCE)
# -----------------------------------------------------------------------
@ -26,6 +32,9 @@ $(LIBBUILD): $(LIBOBJECTS)
$(PROGS): $(LIBOBJECTS)
pack.o:
$(CC) $(CFLAGS) -DVERSION=\"$(VERSION)\" -o $@ -c $<
clean:
rm -f *.a *.o *~ $(PROGS)

44
build/TODO Normal file
View File

@ -0,0 +1,44 @@
> Most of my spec files have empty Distribution: and Vendor: tag because I
> really don't care. Now, empty tags are frowned upon. So, I try to comment
> out the lines and get a funny error message:
>
> Distribution field must be present in package: solaris2.6
> Vendor field must be present in package: solaris2.6
>
> This happens to be my value of 'Build Os' which gets into the error message!
posix %attr
Add Shell: rpmrc entry
some /foo/*/*.foo entries don't get matches
detect multiple summary/description entries
verify langs
=====================================================================
i18n strings
triggers
custom find-requires, find-provides
messages (normal, verbose, debug)
deprecate require_distribution, require_icon, require_vendor
deprecate RPMVAR_ROOT, and the RPMVAR_REQUIRE* stuff above
=======================================================================
* i18n
headerGetRawEntry() -> i18n string
headerAddI18nString(Header, tag, string, lang)
Summary(...):
%description -l ...
%lang(...) <file>
"intl.h"
_("...")

View File

@ -1,751 +1,236 @@
/* RPM - Copyright (C) 1995 Red Hat Software
*
* build.c - routines for preparing and building the sources
*/
#include "miscfn.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
#include <malloc.h>
#include "build.h"
#include "files.h"
#include "header.h"
#include "spec.h"
#include "specP.h"
#include "rpmlib.h"
#include "messages.h"
#include "stringbuf.h"
#include "misc.h"
#include "spec.h"
#include "build.h"
#include "lib/misc.h"
#include "lib/messages.h"
#include "rpmlib.h"
#include "pack.h"
#include "popt/popt.h"
#include "config.h"
#include "files.h"
#include "names.h"
static void doRmSource(Spec spec);
static int writeVars(Spec spec, FILE *f);
struct Script {
char *name;
FILE *file;
};
struct Script *openScript(Spec spec, int builddir, char *name);
void writeScript(struct Script *script, char *s);
int execScript(struct Script *script);
void freeScript(struct Script *script, int test);
int execPart(Spec s, char *sb, char *name, int builddir, int test);
static int doSetupMacro(Spec spec, StringBuf sb, char *line);
static int doPatchMacro(Spec spec, StringBuf sb, char *line);
static char *do_untar(Spec spec, int c, int quietly);
static char *do_patch(Spec spec, int c, int strip, char *dashb,
int reverse, int removeEmpties);
int isCompressed(char *file);
static void doSweep(Spec s);
static int doRmSource(Spec s);
char build_subdir[1024];
struct Script *openScript(Spec spec, int builddir, char *name)
int buildSpec(Spec spec, int what, int test)
{
int x, rc;
if (!spec->inBuildArchitectures && spec->buildArchitectureCount) {
/* When iterating over buildArchitectures, do the source */
/* packaging on the first run, and skip RMSOURCE altogether */
x = 0;
while (x < spec->buildArchitectureCount) {
if ((rc = buildSpec(spec->buildArchitectureSpecs[x],
(what & ~RPMBUILD_RMSOURCE) |
(x ? 0 : (what & RPMBUILD_PACKAGESOURCE)),
test))) {
return rc;
}
x++;
}
} else {
if (what & RPMBUILD_PREP) {
if ((rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test))) {
return rc;
}
}
if (what & RPMBUILD_BUILD) {
if ((rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test))) {
return rc;
}
}
if (what & RPMBUILD_INSTALL) {
if ((rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test))) {
return rc;
}
}
if (what & RPMBUILD_PACKAGESOURCE) {
if ((rc = processSourceFiles(spec))) {
return rc;
}
}
if ((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
(what & RPMBUILD_FILECHECK)) {
if ((rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL))) {
return rc;
}
}
if (what & RPMBUILD_PACKAGESOURCE) {
if ((rc = packageSources(spec))) {
return rc;
}
}
if (what & RPMBUILD_PACKAGEBINARY) {
if ((rc = packageBinaries(spec))) {
return rc;
}
}
if (what & RPMBUILD_CLEAN) {
if ((rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test))) {
return rc;
}
}
if (what & RPMBUILD_RMBUILD) {
if ((rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test))) {
return rc;
}
}
}
if (what & RPMBUILD_RMSOURCE) {
doRmSource(spec);
}
return 0;
}
int doScript(Spec spec, int what, char *name, StringBuf sb, int test)
{
struct Script *script = malloc(sizeof(struct Script));
struct PackageRec *main_package = spec->packages;
char *s, * arch, * os;
int fd;
int_32 foo;
rpmGetArchInfo(&arch, NULL);
rpmGetOsInfo(&os, NULL);
if (! main_package) {
rpmError(RPMERR_INTERNAL, "Empty main package");
exit(RPMERR_INTERNAL);
}
if (makeTempFile(NULL, &script->name, &fd))
exit(1);
script->file = fdopen(fd, "w");
/* Prepare the script */
fprintf(script->file,
"# Script generated by rpm\n\n");
fprintf(script->file, "RPM_SOURCE_DIR=\"%s\"\n", rpmGetVar(RPMVAR_SOURCEDIR));
fprintf(script->file, "RPM_BUILD_DIR=\"%s\"\n", rpmGetVar(RPMVAR_BUILDDIR));
fprintf(script->file, "RPM_DOC_DIR=\"%s\"\n", rpmGetVar(RPMVAR_DEFAULTDOCDIR));
fprintf(script->file, "RPM_OPT_FLAGS=\"%s\"\n", rpmGetVar(RPMVAR_OPTFLAGS));
fprintf(script->file, "RPM_ARCH=\"%s\"\n", arch);
fprintf(script->file, "RPM_OS=\"%s\"\n", os);
if (rpmGetVar(RPMVAR_ROOT)) {
fprintf(script->file, "RPM_ROOT_DIR=\"%s\"\n", rpmGetVar(RPMVAR_ROOT));
} else {
fprintf(script->file, "RPM_ROOT_DIR=\"\"\n");
}
if (rpmGetVar(RPMVAR_BUILDROOT)) {
fprintf(script->file, "RPM_BUILD_ROOT=\"%s\"\n",
rpmGetVar(RPMVAR_BUILDROOT));
} else {
fprintf(script->file, "RPM_BUILD_ROOT=\"\"\n");
}
fprintf(script->file, "RPM_PACKAGE_NAME=\"%s\"\n", spec->name);
headerGetEntry(main_package->header, RPMTAG_VERSION, &foo, (void **)&s, &foo);
fprintf(script->file, "RPM_PACKAGE_VERSION=\"%s\"\n", s);
headerGetEntry(main_package->header, RPMTAG_RELEASE, &foo, (void **)&s, &foo);
fprintf(script->file, "RPM_PACKAGE_RELEASE=\"%s\"\n", s);
if (rpmIsVerbose()) {
fprintf(script->file, "set -x\n\n");
} else {
fprintf(script->file, "exec > /dev/null\n\n");
}
/* Set the umask to a known value */
fprintf(script->file, "umask 022\n");
fprintf(script->file, "\necho Executing: %s\n", name);
fprintf(script->file, "cd %s\n\n", rpmGetVar(RPMVAR_BUILDDIR));
if (builddir) {
/* Need to cd to the actual build directory. */
/* Note that this means we have to parse the */
/* %prep section even if we aren't using it. */
fprintf(script->file, "cd %s\n\n", build_subdir);
}
/* We do a litte sanity check here just to make sure we do not wipe */
/* the system by accident... */
if (rpmGetVar(RPMVAR_BUILDROOT)) {
fprintf(script->file, "if [ -z \"$RPM_BUILD_ROOT\" -o \"$RPM_BUILD_ROOT\" = \"/\" ]; then\n");
fprintf(script->file, " echo\n");
fprintf(script->file, " echo 'Warning: Spec contains BuildRoot: tag that is either empty or is set to \"/\"'\n");
fprintf(script->file, " echo\n");
fprintf(script->file, " exit 1\n");
fprintf(script->file, "fi\n");
}
return script;
}
void writeScript(struct Script *script, char *s)
{
fprintf(script->file, "%s", s);
}
int execScript(struct Script *script)
{
FILE *f;
char *scriptName;
int pid;
int status;
writeScript(script, "\nexit 0;\n");
fclose(script->file);
script->file = NULL;
chmod(script->name, 0600);
if (!(pid = fork())) {
execl("/bin/sh", "/bin/sh", "-e", script->name, script->name, NULL);
rpmError(RPMERR_SCRIPT, "Exec failed");
_exit(RPMERR_SCRIPT);
switch (what) {
case RPMBUILD_PREP:
name = "%prep";
sb = spec->prep;
break;
case RPMBUILD_BUILD:
name = "%build";
sb = spec->build;
break;
case RPMBUILD_INSTALL:
name = "%install";
sb = spec->install;
break;
case RPMBUILD_CLEAN:
name = "%clean";
sb = spec->clean;
break;
case RPMBUILD_RMBUILD:
name = "--clean";
break;
case RPMBUILD_STRINGBUF:
break;
}
wait(&status);
if (! WIFEXITED(status) || WEXITSTATUS(status)) {
rpmError(RPMERR_SCRIPT, "Bad exit status");
exit(RPMERR_SCRIPT);
}
return 0;
}
void freeScript(struct Script *script, int test)
{
if (script->file)
fclose(script->file);
if (! test)
unlink(script->name);
free(script->name);
free(script);
}
int execPart(Spec s, char *sb, char *name, int builddir, int test)
{
struct Script *script;
rpmMessage(RPMMESS_DEBUG, "RUNNING: %s\n", name);
script = openScript(s, builddir, name);
writeScript(script, sb);
if (!test) {
execScript(script);
}
freeScript(script, test);
return 0;
}
static void doSweep(Spec s)
{
char buf[1024];
if (strcmp(build_subdir, ".")) {
struct Script *script;
script = openScript(s, 0, "sweep");
sprintf(buf, "rm -rf %s\n", build_subdir);
writeScript(script, buf);
execScript(script);
freeScript(script, 0);
}
}
static int doRmSource(Spec s)
{
char filename[1024];
struct sources *source;
struct PackageRec *package;
/* spec file */
sprintf(filename, "%s%s", rpmGetVar(RPMVAR_SPECDIR),
strrchr(s->specfile, '/'));
unlink(filename);
/* sources and patches */
source = s->sources;
while (source) {
sprintf(filename, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), source->source);
unlink(filename);
source = source->next;
}
/* icons */
package = s->packages;
while (package) {
if (package->icon) {
sprintf(filename, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR),
package->icon);
unlink(filename);
}
package = package->next;
}
return 0;
}
static int doSetupMacro(Spec spec, StringBuf sb, char *line)
{
char *version;
int leaveDirs = 0, skipDefaultAction = 0;
int createDir = 0, quietly = 0;
char * dirName = NULL;
char buf[1024];
StringBuf before;
StringBuf after;
poptContext optCon;
int argc;
char ** argv;
int arg;
char * optArg;
char * chptr;
int rc;
int num;
struct poptOption optionsTable[] = {
{ NULL, 'a', POPT_ARG_STRING, NULL, 'a' },
{ NULL, 'b', POPT_ARG_STRING, NULL, 'b' },
{ NULL, 'c', 0, &createDir, 0 },
{ NULL, 'D', 0, &leaveDirs, 0 },
{ NULL, 'n', POPT_ARG_STRING, &dirName, 0 },
{ NULL, 'T', 0, &skipDefaultAction, 0 },
{ NULL, 'q', 0, &quietly, 0 },
{ 0, 0, 0, 0, 0 }
};
if ((rc = poptParseArgvString(line, &argc, &argv))) {
rpmError(RPMERR_BADSPEC, "Error parsing %%setup: %s",
poptStrerror(rc));
return RPMERR_BADSPEC;
}
before = newStringBuf();
after = newStringBuf();
optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
while ((arg = poptGetNextOpt(optCon)) > 0) {
optArg = poptGetOptArg(optCon);
/* We only parse -a and -b here */
num = strtoul(optArg, &chptr, 10);
if ((*chptr) || (chptr == optArg) || (num == ULONG_MAX)) {
rpmError(RPMERR_BADSPEC, "Bad arg to %%setup %c: %s", num, optArg);
free(argv);
freeStringBuf(before);
freeStringBuf(after);
poptFreeContext(optCon);
return(RPMERR_BADSPEC);
}
chptr = do_untar(spec, num, quietly);
if (!chptr) return 1;
if (arg == 'a')
appendLineStringBuf(after, chptr);
else
appendLineStringBuf(before, chptr);
}
if (arg < -1) {
rpmError(RPMERR_BADSPEC, "Bad %%setup option %s: %s",
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(arg));
free(argv);
freeStringBuf(before);
freeStringBuf(after);
poptFreeContext(optCon);
return(RPMERR_BADSPEC);
}
if (dirName) {
strcpy(build_subdir, dirName);
} else {
strcpy(build_subdir, spec->name);
strcat(build_subdir, "-");
/* We should already have a version field */
headerGetEntry(spec->packages->header, RPMTAG_VERSION, NULL,
(void *) &version, NULL);
strcat(build_subdir, version);
}
free(argv);
poptFreeContext(optCon);
/* cd to the build dir */
sprintf(buf, "cd %s", rpmGetVar(RPMVAR_BUILDDIR));
appendLineStringBuf(sb, buf);
/* delete any old sources */
if (!leaveDirs) {
sprintf(buf, "rm -rf %s", build_subdir);
appendLineStringBuf(sb, buf);
}
/* if necessary, create and cd into the proper dir */
if (createDir) {
sprintf(buf, "mkdir -p %s\ncd %s", build_subdir, build_subdir);
appendLineStringBuf(sb, buf);
}
/* do the default action */
if (!createDir && !skipDefaultAction) {
chptr = do_untar(spec, 0, quietly);
if (!chptr) return 1;
appendLineStringBuf(sb, chptr);
}
appendStringBuf(sb, getStringBuf(before));
freeStringBuf(before);
if (!createDir) {
sprintf(buf, "cd %s", build_subdir);
appendLineStringBuf(sb, buf);
}
if (createDir && !skipDefaultAction) {
chptr = do_untar(spec, 0, quietly);
if (!chptr) return 1;
appendLineStringBuf(sb, chptr);
}
appendStringBuf(sb, getStringBuf(after));
freeStringBuf(after);
/* clean up permissions etc */
if (!geteuid()) {
appendLineStringBuf(sb, "chown -R root .");
appendLineStringBuf(sb, "chgrp -R root .");
}
if (rpmGetVar(RPMVAR_FIXPERMS)) {
appendStringBuf(sb, "chmod -R ");
appendStringBuf(sb, rpmGetVar(RPMVAR_FIXPERMS));
appendLineStringBuf(sb, " .");
}
return 0;
}
int isCompressed(char *file)
{
int fd;
unsigned char magic[4];
fd = open(file, O_RDONLY);
read(fd, magic, 4);
close(fd);
if (((magic[0] == 0037) && (magic[1] == 0213)) || /* gzip */
((magic[0] == 0037) && (magic[1] == 0236)) || /* old gzip */
((magic[0] == 0037) && (magic[1] == 0036)) || /* pack */
((magic[0] == 0037) && (magic[1] == 0240)) || /* SCO lzh */
((magic[0] == 0037) && (magic[1] == 0235)) || /* compress */
((magic[0] == 0120) && (magic[1] == 0113) &&
(magic[2] == 0003) && (magic[3] == 0004)) /* pkzip */
) {
return 1;
}
return 0;
}
static char *do_untar(Spec spec, int c, int quietly)
{
static char buf[1024];
char file[1024];
char *s, *taropts;
struct sources *sp;
s = NULL;
sp = spec->sources;
while (sp) {
if ((sp->ispatch == 0) && (sp->num == c)) {
s = sp->source;
break;
}
sp = sp->next;
}
if (! s) {
rpmError(RPMERR_BADSPEC, "No source number %d", c);
return NULL;
}
sprintf(file, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), s);
taropts = (rpmIsVerbose() && !quietly ? "-xvvf" : "-xf");
if (isCompressed(file)) {
sprintf(buf,
"%s -dc %s | tar %s -\n"
"if [ $? -ne 0 ]; then\n"
" exit $?\n"
"fi",
rpmGetVar(RPMVAR_GZIPBIN), file, taropts);
} else {
sprintf(buf, "tar %s %s", taropts, file);
}
return buf;
}
static char *do_patch(Spec spec, int c, int strip, char *db,
int reverse, int removeEmpties)
{
static char buf[1024];
char file[1024];
char args[1024];
char *s;
struct sources *sp;
s = NULL;
sp = spec->sources;
while (sp) {
if ((sp->ispatch == 1) && (sp->num == c)) {
s = sp->source;
break;
}
sp = sp->next;
}
if (! s) {
rpmError(RPMERR_BADSPEC, "No patch number %d", c);
return NULL;
}
sprintf(file, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), s);
args[0] = '\0';
if (db) {
#if HAVE_OLDPATCH_21 == 0
strcat(args, "-b ");
#endif
strcat(args, "--suffix ");
strcat(args, db);
}
if (reverse) {
strcat(args, " -R");
}
if (removeEmpties) {
strcat(args, " -E");
}
if (isCompressed(file)) {
sprintf(buf,
"echo \"Patch #%d:\"\n"
"%s -dc %s | patch -p%d %s -s\n"
"if [ $? -ne 0 ]; then\n"
" exit $?\n"
"fi",
c, rpmGetVar(RPMVAR_GZIPBIN), file, strip, args);
} else {
sprintf(buf,
"echo \"Patch #%d:\"\n"
"patch -p%d %s -s < %s", c, strip, args, file);
}
return buf;
}
static int doPatchMacro(Spec spec, StringBuf sb, char *line)
{
char *opt_b;
int opt_P, opt_p, opt_R, opt_E;
char *s, *s1;
char buf[1024];
int patch_nums[1024]; /* XXX - we can only handle 1024 patches! */
int patch_index, x;
opt_P = opt_p = opt_R = opt_E = 0;
opt_b = NULL;
patch_index = 0;
if (! strchr(" \t\n", line[6])) {
/* %patchN */
sprintf(buf, "%%patch -P %s", line + 6);
} else {
strcpy(buf, line);
}
strtok(buf, " \t\n"); /* remove %patch */
while ((s = strtok(NULL, " \t\n"))) {
if (!strcmp(s, "-P")) {
opt_P = 1;
} else if (!strcmp(s, "-R")) {
opt_R = 1;
} else if (!strcmp(s, "-E")) {
opt_E = 1;
} else if (!strcmp(s, "-b")) {
/* orig suffix */
opt_b = strtok(NULL, " \t\n");
if (! opt_b) {
rpmError(RPMERR_BADSPEC, "Need arg to %%patch -b");
return(RPMERR_BADSPEC);
}
} else if (!strncmp(s, "-p", 2)) {
/* unfortunately, we must support -pX */
if (! strchr(" \t\n", s[2])) {
s = s + 2;
} else {
s = strtok(NULL, " \t\n");
if (! s) {
rpmError(RPMERR_BADSPEC, "Need arg to %%patch -p");
return(RPMERR_BADSPEC);
}
}
s1 = NULL;
opt_p = strtoul(s, &s1, 10);
if ((*s1) || (s1 == s) || (opt_p == ULONG_MAX)) {
rpmError(RPMERR_BADSPEC, "Bad arg to %%patch -p: %s", s);
return(RPMERR_BADSPEC);
}
} else {
/* Must be a patch num */
if (patch_index == 1024) {
rpmError(RPMERR_BADSPEC, "Too many patches!");
return(RPMERR_BADSPEC);
}
s1 = NULL;
patch_nums[patch_index] = strtoul(s, &s1, 10);
if ((*s1) || (s1 == s) || (patch_nums[patch_index] == ULONG_MAX)) {
rpmError(RPMERR_BADSPEC, "Bad arg to %%patch: %s", s);
return(RPMERR_BADSPEC);
}
patch_index++;
}
}
/* All args processed */
if (! opt_P) {
s = do_patch(spec, 0, opt_p, opt_b, opt_R, opt_E);
if (! s) {
return 1;
}
appendLineStringBuf(sb, s);
}
x = 0;
while (x < patch_index) {
s = do_patch(spec, patch_nums[x], opt_p, opt_b, opt_R, opt_E);
if (! s) {
return 1;
}
appendLineStringBuf(sb, s);
x++;
}
return 0;
}
static int checkSources(Spec s)
{
struct sources *source;
struct PackageRec *package;
char buf[1024];
/* Check that we can access all the sources */
source = s->sources;
while (source) {
sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), source->source);
if (access(buf, R_OK)) {
rpmError(RPMERR_BADSPEC, "missing source or patch: %s", buf);
return RPMERR_BADSPEC;
}
source = source->next;
}
/* ... and icons */
package = s->packages;
while (package) {
if (package->icon) {
sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), package->icon);
if (access(buf, R_OK)) {
rpmError(RPMERR_BADSPEC, "missing icon: %s", buf);
return RPMERR_BADSPEC;
}
}
package = package->next;
}
return 0;
}
int execPrep(Spec s, int really_exec, int test)
{
char **lines, **lines1, *p;
StringBuf out;
int res;
if (checkSources(s)) {
return 1;
}
out = newStringBuf();
p = getStringBuf(s->prep);
lines = splitString(p, strlen(p), '\n');
lines1 = lines;
while (*lines) {
if (! strncmp(*lines, "%setup", 6)) {
if (doSetupMacro(s, out, *lines)) {
return 1;
}
} else if (! strncmp(*lines, "%patch", 6)) {
if (doPatchMacro(s, out, *lines)) {
return 1;
}
} else {
appendLineStringBuf(out, *lines);
}
lines++;
}
freeSplitString(lines1);
res = 0;
if (really_exec) {
res = execPart(s, getStringBuf(out), "%prep", 0, test);
}
freeStringBuf(out);
return res;
}
int execBuild(Spec s, int test)
{
return execPart(s, getStringBuf(s->build), "%build", 1, test);
}
int execInstall(Spec s, int test)
{
int res;
if ((res = execPart(s, getStringBuf(s->install), "%install", 1, test))) {
return res;
}
if ((res = finish_filelists(s))) {
return res;
}
return execPart(s, getStringBuf(s->doc), "special doc", 1, test);
}
int execClean(Spec s)
{
return execPart(s, getStringBuf(s->clean), "%clean", 1, 0);
}
int verifyList(Spec s)
{
int res;
if ((res = finish_filelists(s))) {
return res;
}
return packageBinaries(s, NULL, PACK_NOPACKAGE);
}
int doBuild(Spec s, int flags, char *passPhrase)
{
int test;
test = flags & RPMBUILD_TEST;
strcpy(build_subdir, ".");
if (s->buildArch) {
rpmSetMachine(s->buildArch, NULL);
}
/* We always need to parse the %prep section */
if (execPrep(s, (flags & RPMBUILD_PREP), test)) {
return 1;
}
if (flags & RPMBUILD_LIST)
return verifyList(s);
if (flags & RPMBUILD_BUILD) {
if (execBuild(s, test)) {
return 1;
}
}
if (flags & RPMBUILD_INSTALL) {
if (execInstall(s, test)) {
return 1;
}
}
if (test) {
if ((what != RPMBUILD_RMBUILD) && !sb) {
return 0;
}
markBuildTime();
if (makeTempFile(NULL, &scriptName, &fd)) {
rpmError(RPMERR_SCRIPT, "Unable to open temp file");
return RPMERR_SCRIPT;
}
f = fdopen(fd, "w");
if (flags & RPMBUILD_BINARY) {
if (packageBinaries(s, passPhrase, PACK_PACKAGE)) {
return 1;
}
if (execClean(s)) {
return 1;
}
if (writeVars(spec, f)) {
fclose(f);
FREE(scriptName);
return RPMERR_SCRIPT;
}
fprintf(f, rpmIsVerbose() ? "set -x\n\n" : "exec > /dev/null\n\n");
fprintf(f, "umask 022\n");
fprintf(f, "cd %s\n", rpmGetVar(RPMVAR_BUILDDIR));
if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD) {
fprintf(f, "cd %s\n", spec->buildSubdir);
}
if (what == RPMBUILD_RMBUILD) {
fprintf(f, "rm -rf %s\n", spec->buildSubdir);
} else {
fprintf(f, "%s", getStringBuf(sb));
}
fprintf(f, "\nexit 0\n");
fclose(f);
chmod(scriptName, 0600);
if (flags & RPMBUILD_SOURCE) {
if (packageSource(s, passPhrase)) {
return 1;
}
if (test) {
FREE(scriptName);
return 0;
}
if (flags & RPMBUILD_SWEEP) {
doSweep(s);
rpmMessage(RPMMESS_NORMAL, "Executing: %s\n", name);
if (!(pid = fork())) {
execl("/bin/sh", "/bin/sh", "-e", scriptName, scriptName, NULL);
rpmError(RPMERR_SCRIPT, "Exec of %s failed (%s)",
scriptName, name);
FREE(scriptName);
return RPMERR_SCRIPT;
}
if (flags & RPMBUILD_RMSOURCE) {
doRmSource(s);
wait(&status);
if (! WIFEXITED(status) || WEXITSTATUS(status)) {
rpmError(RPMERR_SCRIPT, "Bad exit status from %s (%s)",
scriptName, name);
FREE(scriptName);
return RPMERR_SCRIPT;
}
unlink(scriptName);
FREE(scriptName);
return 0;
}
static int writeVars(Spec spec, FILE *f)
{
char *arch, *os, *s;
rpmGetArchInfo(&arch, NULL);
rpmGetOsInfo(&os, NULL);
fprintf(f, "export RPM_SOURCE_DIR=\"%s\"\n", rpmGetVar(RPMVAR_SOURCEDIR));
fprintf(f, "export RPM_BUILD_DIR=\"%s\"\n", rpmGetVar(RPMVAR_BUILDDIR));
fprintf(f, "export RPM_DOC_DIR=\"%s\"\n", spec->docDir);
fprintf(f, "export RPM_OPT_FLAGS=\"%s\"\n", rpmGetVar(RPMVAR_OPTFLAGS));
fprintf(f, "export RPM_ARCH=\"%s\"\n", arch);
fprintf(f, "export RPM_OS=\"%s\"\n", os);
if (spec->buildRoot) {
fprintf(f, "export RPM_BUILD_ROOT=\"%s\"\n", spec->buildRoot);
/* This could really be checked internally */
fprintf(f, "if [ -z \"$RPM_BUILD_ROOT\" -o -z \"`echo $RPM_BUILD_ROOT | sed -e 's#/##g'`\" ]; then\n");
fprintf(f, " echo 'Warning: Spec contains BuildRoot: tag that is either empty or is set to \"/\"'\n");
fprintf(f, " exit 1\n");
fprintf(f, "fi\n");
}
headerGetEntry(spec->packages->header, RPMTAG_NAME,
NULL, (void **)&s, NULL);
fprintf(f, "export RPM_PACKAGE_NAME=\"%s\"\n", s);
headerGetEntry(spec->packages->header, RPMTAG_VERSION,
NULL, (void **)&s, NULL);
fprintf(f, "export RPM_PACKAGE_VERSION=\"%s\"\n", s);
headerGetEntry(spec->packages->header, RPMTAG_RELEASE,
NULL, (void **)&s, NULL);
fprintf(f, "export RPM_PACKAGE_RELEASE=\"%s\"\n", s);
return 0;
}
static void doRmSource(Spec spec)
{
struct Source *p;
char buf[BUFSIZ];
unlink(spec->specFile);
p = spec->sources;
while (p) {
if (! (p->flags & RPMBUILD_ISNO)) {
sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), p->source);
unlink(buf);
}
p = p->next;
}
}

View File

@ -1,25 +1,16 @@
#ifndef _BUILD_H_
#define _BUILD_H_
#include "spec.h"
int doBuild(Spec s, int flags, char *passPhrase);
int execPrep(Spec s, int really_exec, int test);
int execBuild(Spec s, int test);
int execInstall(Spec s, int test);
int execClean(Spec s);
int verifyList(Spec s);
#define RPMBUILD_PREP (1 << 0)
#define RPMBUILD_BUILD (1 << 1)
#define RPMBUILD_INSTALL (1 << 2)
#define RPMBUILD_CLEAN (1 << 3)
#define RPMBUILD_FILECHECK (1 << 4)
#define RPMBUILD_PACKAGESOURCE (1 << 5)
#define RPMBUILD_PACKAGEBINARY (1 << 6)
#define RPMBUILD_RMSOURCE (1 << 7)
#define RPMBUILD_RMBUILD (1 << 8)
#define RPMBUILD_STRINGBUF (1 << 9) /* only for doScript() */
extern char build_subdir[1024];
int buildSpec(Spec spec, int what, int test);
#define RPMBUILD_PREP 1
#define RPMBUILD_BUILD (1 << 1)
#define RPMBUILD_INSTALL (1 << 2)
#define RPMBUILD_BINARY (1 << 3)
#define RPMBUILD_SOURCE (1 << 4)
#define RPMBUILD_SWEEP (1 << 5)
#define RPMBUILD_LIST (1 << 6)
#define RPMBUILD_RMSOURCE (1 << 7)
#define RPMBUILD_TEST (1 << 8)
#endif _BUILD_H_
int doScript(Spec spec, int what, char *name, StringBuf sb, int test);

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,8 @@
#ifndef _FILES_H_
#define _FILES_H_
#include "spec.h"
#include "specP.h"
#include "stringbuf.h"
#include "package.h"
#include "lib/cpio.h"
int finish_filelists(Spec spec);
int process_filelist(Header header, struct PackageRec *pr, StringBuf sb,
int *size, char *name, char *version,
char *release, int type, char *prefix, char *specFile);
#endif _FILES_H_
int processBinaryFiles(Spec spec, int installSpecialDoc);
int processSourceFiles(Spec spec);
void freeCpioList(struct cpioFileMapping *cpioList, int cpioCount);

View File

@ -4,48 +4,42 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "macro.h"
#ifdef DEBUG
#include "macro.h"
#include "misc.h"
#ifdef DEBUG_MACROS
#include <stdio.h>
#define rpmError fprintf
#define RPMERR_BADSPEC stderr
static void dumpTable(void);
#else
#include "rpmlib.h"
#include "lib/rpmlib.h"
#endif
static void expandMacroTable(void);
static void expandMacroTable(struct MacroContext *mc);
static int compareMacros(const void *ap, const void *bp);
static struct macroEntry *findEntry(char *name);
static int handleDefine(char *buf);
static struct MacroEntry *findEntry(struct MacroContext *mc, char *name);
static int handleDefine(struct MacroContext *mc, char *buf);
static int parseMacro(char *p, char **macro, char **next);
/* This should be a hash table, but I doubt anyone will ever notice */
/* This should be a hash table, but I doubt anyone would ever */
/* notice the increase is speed. */
#define MACRO_CHUNK_SIZE 16
struct macroEntry {
char *name;
char *expansion;
};
static struct macroEntry *macroTable = NULL;
static int macrosAllocated = 0;
static int firstFree = 0;
/*************************************************************************/
/* */
/* Parsing routines */
/* */
/*************************************************************************/
int expandMacros(char *buf)
int expandMacros(struct MacroContext *mc, char *buf)
{
char bufA[1024];
char *copyTo, *copyFrom;
char *name, *rest, *first;
struct macroEntry *p;
struct MacroEntry *p;
if (! buf) {
return 0;
@ -57,6 +51,7 @@ int expandMacros(char *buf)
first++;
}
if (*first == '#') {
buf[0] = '\0';
return 0;
}
@ -70,8 +65,8 @@ int expandMacros(char *buf)
if (parseMacro(copyFrom+1, &name, &rest)) {
return 1;
}
if (!strcmp(name, "define")) {
if (handleDefine(rest)) {
if (copyFrom == buf && !strcmp(name, "define")) {
if (handleDefine(mc, rest)) {
return 1;
}
/* result is empty */
@ -83,7 +78,7 @@ int expandMacros(char *buf)
copyFrom = rest;
} else {
/* a real live macro! */
p = findEntry(name);
p = findEntry(mc, name);
if (! p) {
/* undefined - just leave it */
*copyTo++ = '%';
@ -116,7 +111,7 @@ static int parseMacro(char *p, char **macro, char **next)
if (! p) {
/* empty macro name */
rpmError(RPMERR_BADSPEC, "Empty macro name\n");
rpmError(RPMERR_BADSPEC, "Empty macro name");
return 2;
}
@ -124,14 +119,14 @@ static int parseMacro(char *p, char **macro, char **next)
*next = strchr(p, '}');
if (! *next) {
/* unterminated */
rpmError(RPMERR_BADSPEC, "Unterminated {: %s\n", p);
rpmError(RPMERR_BADSPEC, "Unterminated {: %s", p);
return 1;
}
**next = '\0';
*macro = strtok(p+1, " \n\t");
if (! *macro) {
/* empty macro name */
rpmError(RPMERR_BADSPEC, "Empty macro name\n");
rpmError(RPMERR_BADSPEC, "Empty macro name");
return 2;
}
(*next)++;
@ -146,7 +141,7 @@ static int parseMacro(char *p, char **macro, char **next)
if (isspace(*p) || ! *p) {
/* illegal % syntax */
rpmError(RPMERR_BADSPEC, "Illegal %% syntax: %s\n", p);
rpmError(RPMERR_BADSPEC, "Illegal %% syntax: %s", p);
return 3;
}
@ -165,7 +160,7 @@ static int parseMacro(char *p, char **macro, char **next)
return 0;
}
static int handleDefine(char *buf)
static int handleDefine(struct MacroContext *mc, char *buf)
{
char *last, *name, *expansion;
@ -177,7 +172,7 @@ static int handleDefine(char *buf)
}
if (! *name) {
/* missing macro name */
rpmError(RPMERR_BADSPEC, "Unfinished %%define\n");
rpmError(RPMERR_BADSPEC, "Unfinished %%define");
return 1;
}
expansion = name;
@ -201,13 +196,96 @@ static int handleDefine(char *buf)
}
}
expandMacros(expansion);
addMacro(name, expansion);
expandMacros(mc, expansion);
addMacro(mc, name, expansion);
return 0;
}
#ifdef DEBUG
/*************************************************************************/
/* */
/* Table handling routines */
/* */
/*************************************************************************/
void initMacros(struct MacroContext *mc)
{
mc->macrosAllocated = 0;
mc->firstFree = 0;
mc->macroTable = NULL;
expandMacroTable(mc);
}
void freeMacros(struct MacroContext *mc)
{
int i;
for (i = 0; i < mc->firstFree; i++) {
FREE(mc->macroTable[i].name);
FREE(mc->macroTable[i].expansion);
}
FREE(mc->macroTable);
}
void addMacro(struct MacroContext *mc, char *name, char *expansion)
{
struct MacroEntry *p;
p = findEntry(mc, name);
if (p) {
free(p->expansion);
p->expansion = strdup(expansion);
return;
}
if (mc->firstFree == mc->macrosAllocated) {
expandMacroTable(mc);
}
p = mc->macroTable + mc->firstFree++;
p->name = strdup(name);
p->expansion = strdup(expansion);
qsort(mc->macroTable, mc->firstFree, sizeof(*(mc->macroTable)),
compareMacros);
}
static struct MacroEntry *findEntry(struct MacroContext *mc, char *name)
{
struct MacroEntry key;
if (! mc->firstFree) {
return NULL;
}
key.name = name;
return bsearch(&key, mc->macroTable, mc->firstFree,
sizeof(*(mc->macroTable)), compareMacros);
}
static int compareMacros(const void *ap, const void *bp)
{
return strcmp(((struct MacroEntry *)ap)->name,
((struct MacroEntry *)bp)->name);
}
static void expandMacroTable(struct MacroContext *mc)
{
mc->macrosAllocated += MACRO_CHUNK_SIZE;
if (! mc->macrosAllocated) {
mc->macroTable = malloc(sizeof(*(mc->macroTable)) *
mc->macrosAllocated);
mc->firstFree = 0;
} else {
mc->macroTable = realloc(mc->macroTable, sizeof(*(mc->macroTable)) *
mc->macrosAllocated);
}
}
/***********************************************************************/
#ifdef DEBUG_MACROS
static void dumpTable()
{
int i;
@ -230,77 +308,3 @@ void main(void)
}
#endif
/*************************************************************************/
/* */
/* Table handling routines */
/* */
/*************************************************************************/
void resetMacros(void)
{
int i;
if (! macrosAllocated) {
expandMacroTable();
return;
}
for (i = 0; i < firstFree; i++) {
free(macroTable[i].name);
free(macroTable[i].expansion);
}
firstFree = 0;
}
void addMacro(char *name, char *expansion)
{
struct macroEntry *p;
p = findEntry(name);
if (p) {
free(p->expansion);
p->expansion = strdup(expansion);
return;
}
if (firstFree == macrosAllocated) {
expandMacroTable();
}
p = macroTable + firstFree++;
p->name = strdup(name);
p->expansion = strdup(expansion);
qsort(macroTable, firstFree, sizeof(*macroTable), compareMacros);
}
static struct macroEntry *findEntry(char *name)
{
struct macroEntry key;
if (! firstFree) {
return NULL;
}
key.name = name;
return bsearch(&key, macroTable, firstFree,
sizeof(*macroTable), compareMacros);
}
static int compareMacros(const void *ap, const void *bp)
{
return strcmp(((struct macroEntry *)ap)->name,
((struct macroEntry *)bp)->name);
}
static void expandMacroTable()
{
macrosAllocated += MACRO_CHUNK_SIZE;
if (! macrosAllocated) {
macroTable = malloc(sizeof(*macroTable) * macrosAllocated);
firstFree = 0;
} else {
macroTable = realloc(macroTable,
sizeof(*macroTable) * macrosAllocated);
}
}

View File

@ -1,8 +1,25 @@
#ifndef _MACRO_H_
#define _MACRO_H_
/* macro.h - %macro handling */
void resetMacros(void);
struct MacroEntry {
char *name;
char *expansion;
};
void addMacro(char *name, char *expansion);
struct MacroContext {
struct MacroEntry *macroTable;
int macrosAllocated;
int firstFree;
};
void initMacros(struct MacroContext *mc);
void freeMacros(struct MacroContext *mc);
void addMacro(struct MacroContext *mc, char *name, char *expansion);
/* Expand all macros in buf, in place */
int expandMacros(char *buf);
int expandMacros(struct MacroContext *mc, char *buf);
#endif

202
build/misc.c Normal file
View File

@ -0,0 +1,202 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include "misc.h"
#include "spec.h"
#include "rpmlib.h"
#include "header.h"
#include "popt/popt.h"
void addOrAppendListEntry(Header h, int_32 tag, char *line)
{
int argc;
char **argv;
poptParseArgvString(line, &argc, &argv);
if (argc) {
headerAddOrAppendEntry(h, tag, RPM_STRING_ARRAY_TYPE, argv, argc);
}
FREE(argv);
}
/* Parse a simple part line that only take -n <pkg> or <pkg> */
/* <pkg> is return in name as a pointer into a static buffer */
int parseSimplePart(char *line, char **name, int *flag)
{
char *tok;
char linebuf[BUFSIZ];
static char buf[BUFSIZ];
strcpy(linebuf, line);
/* Throw away the first token (the %xxxx) */
strtok(linebuf, " \t\n");
if (!(tok = strtok(NULL, " \t\n"))) {
*name = NULL;
return 0;
}
if (!strcmp(tok, "-n")) {
if (!(tok = strtok(NULL, " \t\n"))) {
return 1;
}
*flag = PART_NAME;
} else {
*flag = PART_SUBNAME;
}
strcpy(buf, tok);
*name = buf;
return (strtok(NULL, " \t\n")) ? 1 : 0;
}
int parseYesNo(char *s)
{
if (!s || (s[0] == 'n' || s[0] == 'N') ||
!strcasecmp(s, "false") ||
!strcasecmp(s, "off") ||
!strcmp(s, "0")) {
return 0;
}
return 1;
}
char *findLastChar(char *s)
{
char *res = s;
while (*s) {
if (! isspace(*s)) {
res = s;
}
s++;
}
return res;
}
int parseNum(char *line, int *res)
{
char *s1;
s1 = NULL;
*res = strtoul(line, &s1, 10);
if ((*s1) || (s1 == line) || (*res == ULONG_MAX)) {
return 1;
}
return 0;
}
StringBuf getOutputFrom(char *dir, char *argv[],
char *writePtr, int writeBytesLeft,
int failNonZero)
{
int progPID;
int progDead;
int toProg[2];
int fromProg[2];
int status;
void *oldhandler;
int bytesWritten;
StringBuf readBuff;
int bytes;
unsigned char buf[8193];
oldhandler = signal(SIGPIPE, SIG_IGN);
pipe(toProg);
pipe(fromProg);
if (!(progPID = fork())) {
close(toProg[1]);
close(fromProg[0]);
dup2(toProg[0], 0); /* Make stdin the in pipe */
dup2(fromProg[1], 1); /* Make stdout the out pipe */
close(toProg[0]);
close(fromProg[1]);
if (dir) {
chdir(dir);
}
execvp(argv[0], argv);
rpmError(RPMERR_EXEC, "Couldn't exec %s", argv[0]);
_exit(RPMERR_EXEC);
}
if (progPID < 0) {
rpmError(RPMERR_FORK, "Couldn't fork %s", argv[0]);
return NULL;
}
close(toProg[0]);
close(fromProg[1]);
/* Do not block reading or writing from/to prog. */
fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
fcntl(toProg[1], F_SETFL, O_NONBLOCK);
readBuff = newStringBuf();
progDead = 0;
do {
if (waitpid(progPID, &status, WNOHANG)) {
progDead = 1;
}
/* Write some stuff to the process if possible */
if (writeBytesLeft) {
if ((bytesWritten =
write(toProg[1], writePtr,
(1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
if (errno != EAGAIN) {
perror("getOutputFrom()");
exit(1);
}
bytesWritten = 0;
}
writeBytesLeft -= bytesWritten;
writePtr += bytesWritten;
} else {
close(toProg[1]);
}
/* Read any data from prog */
bytes = read(fromProg[0], buf, sizeof(buf)-1);
while (bytes > 0) {
buf[bytes] = '\0';
appendStringBuf(readBuff, buf);
bytes = read(fromProg[0], buf, sizeof(buf)-1);
}
/* terminate when prog dies */
} while (!progDead);
close(toProg[1]);
close(fromProg[0]);
signal(SIGPIPE, oldhandler);
if (writeBytesLeft) {
rpmError(RPMERR_EXEC, "failed to write all data to %s", argv[0]);
return NULL;
}
waitpid(progPID, &status, 0);
if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
rpmError(RPMERR_EXEC, "%s failed", argv[0]);
return NULL;
}
return readBuff;
}

27
build/misc.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef _MISC_H_
#define _MISC_H_
#include "spec.h"
#include "ctype.h"
#define FREE(x) { if (x) free(x); x = NULL; }
#define SKIPSPACE(s) { while (*(s) && isspace(*(s))) (s)++; }
#define SKIPNONSPACE(s) { while (*(s) && !isspace(*(s))) (s)++; }
#define SKIPTONEWLINE(s) { while (*s && *s != '\n') s++; }
#define PART_SUBNAME 0
#define PART_NAME 1
void addOrAppendListEntry(Header h, int_32 tag, char *line);
int parseSimplePart(char *line, char **name, int *flag);
char *findLastChar(char *s);
int parseYesNo(char *s);
int parseNum(char *line, int *res);
StringBuf getOutputFrom(char *dir, char *argv[],
char *writePtr, int writeBytesLeft,
int failNonZero);
#endif

View File

@ -56,9 +56,8 @@ Cambridge, MA 02139, USA. */
static int
myftw_dir (DIR **dirs, int level, int descriptors,
char *dir, size_t len,
int (*func) (const char *file,
struct stat *status,
int flag))
int (*func) (void *fl, char *name, struct stat *statp),
void *fl)
{
int got;
struct dirent *entry;
@ -127,13 +126,13 @@ myftw_dir (DIR **dirs, int level, int descriptors,
else
flag = MYFTW_F;
retval = (*func) (dir, &s, flag);
retval = (*func) (fl, dir, &s);
if (flag == MYFTW_D)
{
if (retval == 0)
retval = myftw_dir (dirs, newlev, descriptors, dir,
d_namlen + len, func);
d_namlen + len, func, fl);
if (dirs[newlev] != NULL)
{
int save;
@ -175,10 +174,9 @@ myftw_dir (DIR **dirs, int level, int descriptors,
int myftw (const char *dir,
int (*func) (const char *file,
struct stat *status,
int flag),
int descriptors)
int descriptors,
int (*func) (void *fl, char *name, struct stat *statp),
void *fl)
{
DIR **dirs;
size_t len;
@ -223,12 +221,12 @@ int myftw (const char *dir,
len = strlen (dir);
memcpy ((void *) buf, (void *) dir, len + 1);
retval = (*func) (buf, &s, flag);
retval = (*func) (fl, buf, &s);
if (flag == MYFTW_D)
{
if (retval == 0)
retval = myftw_dir (dirs, 0, descriptors, buf, len, func);
retval = myftw_dir (dirs, 0, descriptors, buf, len, func, fl);
if (dirs[0] != NULL)
{
int save;

View File

@ -3,6 +3,8 @@
#ifndef _MYFTW_H_
#define _MYFTW_H_
#include <sys/stat.h>
/* The FLAG argument to the user function passed to ftw. */
#define MYFTW_F 0 /* Regular file. */
#define MYFTW_D 1 /* Directory. */
@ -10,9 +12,8 @@
#define MYFTW_NS 3 /* Unstatable file. */
int myftw (const char *dir,
int (*func) (const char *file,
struct stat *status,
int flag),
int descriptors);
int descriptors,
int (*func) (void *fl, char *name, struct stat *statp),
void *fl);
#endif _MYFTW_H_

View File

@ -22,8 +22,6 @@ static gid_t gids[1024];
static char *gnames[1024];
static int gid_used = 0;
static time_t buildtime;
/*
* getUname() takes a uid, gets the username, and creates an entry in the
* table to hold a string containing the user name.
@ -162,14 +160,15 @@ char *getGnameS(char *gname)
return gnames[x];
}
void markBuildTime(void)
{
buildtime = time(NULL);
}
time_t *getBuildTime(void)
{
return &buildtime;
static time_t buildTime = 0;
if (! buildTime) {
buildTime = time(NULL);
}
return &buildTime;
}
char *buildHost(void)

View File

@ -11,7 +11,6 @@ char *getGname(gid_t gid);
char *getGnameS(char *gname);
char *buildHost(void);
void markBuildTime(void);
time_t *getBuildTime(void);
#endif _NAMES_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,4 @@
/* pack.h -- final packing steps */
#ifndef _PACK_H_
#define _PACK_H_
#include "spec.h"
#define PACK_PACKAGE 1
#define PACK_NOPACKAGE 0
int packageBinaries(Spec s, char *passPhrase, int doPackage);
int packageSource(Spec s, char *passPhrase);
#endif _PACK_H_
int packageBinaries(Spec spec);
int packageSources(Spec spec);

128
build/package.c Normal file
View File

@ -0,0 +1,128 @@
#include "spec.h"
#include "package.h"
#include "misc.h"
#include "rpmlib.h"
#include "files.h"
#include <malloc.h>
int lookupPackage(Spec spec, char *name, int flag, Package *pkg)
{
char buf[BUFSIZ];
char *n, *fullName;
Package p;
/* "main" package */
if (! name) {
if (pkg) {
*pkg = spec->packages;
}
return 0;
}
/* Construct package name */
if (flag == PART_SUBNAME) {
headerGetEntry(spec->packages->header, RPMTAG_NAME,
NULL, (void *) &n, NULL);
sprintf(buf, "%s-%s", n, name);
fullName = buf;
} else {
fullName = name;
}
p = spec->packages;
while (p) {
headerGetEntry(p->header, RPMTAG_NAME, NULL, (void *) &n, NULL);
if (n && (! strcmp(fullName, n))) {
if (pkg) {
*pkg = p;
}
return 0;
}
p = p->next;
}
if (pkg) {
*pkg = NULL;
}
return 1;
}
Package newPackage(Spec spec)
{
Package p;
Package pp;
p = malloc(sizeof(*p));
p->header = headerNew();
p->icon = NULL;
p->autoReqProv = 1;
#if 0
p->reqProv = NULL;
p->triggers = NULL;
p->triggerScripts = NULL;
#endif
p->fileFile = NULL;
p->fileList = NULL;
p->next = NULL;
p->cpioList = NULL;
p->cpioCount = 0;
p->preInFile = NULL;
p->postInFile = NULL;
p->preUnFile = NULL;
p->postUnFile = NULL;
p->verifyFile = NULL;
p->specialDoc = NULL;
if (! spec->packages) {
spec->packages = p;
} else {
/* Always add package to end of list */
pp = spec->packages;
while (pp->next) {
pp = pp->next;
}
pp->next = p;
}
return p;
}
void freePackages(Spec spec)
{
Package p;
while (spec->packages) {
p = spec->packages;
spec->packages = p->next;
freePackage(p);
}
}
void freePackage(Package p)
{
if (! p) {
return;
}
FREE(p->preInFile);
FREE(p->postInFile);
FREE(p->preUnFile);
FREE(p->postUnFile);
FREE(p->verifyFile);
headerFree(p->header);
freeStringBuf(p->fileList);
FREE(p->fileFile);
freeCpioList(p->cpioList, p->cpioCount);
freeStringBuf(p->specialDoc);
free(p);
}

9
build/package.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _PACKAGE_H_
#define _PACKAGE_H_
int lookupPackage(Spec spec, char *name, int flag, Package *pkg);
Package newPackage(Spec spec);
void freePackages(Spec spec);
void freePackage(Package p);
#endif

17
build/parse.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef _PARSE_H_
#define _PARSE_H_
int parseChangelog(Spec spec);
int parseDescription(Spec spec);
int parseFiles(Spec spec);
int parsePreamble(Spec spec, int initialPackage);
int parsePrep(Spec spec);
int parseRequiresConflicts(Spec spec, Package pkg, char *field, int tag);
int parseProvidesObsoletes(Spec spec, Package pkg, char *field, int tag);
int parseScript(Spec spec, int parsePart);
int parseBuildInstallClean(Spec spec, int parsePart);
int parseSpec(Spec *specp, char *specFile, char *buildRoot,
int inBuildArch, char *passPhrase, char *cookie);
#endif

View File

@ -0,0 +1,46 @@
#include "read.h"
#include "part.h"
#include "rpmlib.h"
int parseBuildInstallClean(Spec spec, int parsePart)
{
int nextPart;
StringBuf *sbp = NULL;
char *name = NULL;
switch (parsePart) {
case PART_BUILD:
sbp = &(spec->build);
name = "%build";
break;
case PART_INSTALL:
sbp = &(spec->install);
name = "%install";
break;
case PART_CLEAN:
sbp = &(spec->clean);
name = "%clean";
break;
}
if (*sbp) {
rpmError(RPMERR_BADSPEC, "line %d: second %s", spec->lineNum, name);
return RPMERR_BADSPEC;
}
*sbp = newStringBuf();
/* There are no options to %build, %install, or %clean */
if (readLine(spec, STRIP_NOTHING) > 0) {
return PART_NONE;
}
while (! (nextPart = isPart(spec->line))) {
appendLineStringBuf(*sbp, spec->line);
if (readLine(spec, STRIP_NOTHING) > 0) {
return PART_NONE;
}
}
return nextPart;
}

211
build/parseChangelog.c Normal file
View File

@ -0,0 +1,211 @@
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include "read.h"
#include "part.h"
#include "stringbuf.h"
#include "misc.h"
#include "header.h"
#include "rpmlib.h"
static void addChangelogEntry(Header h, int time, char *name, char *text);
static int addChangelog(Header h, StringBuf sb);
static int dateToTimet(const char * datestr, time_t * secs);
int parseChangelog(Spec spec)
{
int nextPart, res;
StringBuf sb;
sb = newStringBuf();
/* There are no options to %changelog */
if (readLine(spec, STRIP_NOTHING) > 0) {
freeStringBuf(sb);
return PART_NONE;
}
while (! (nextPart = isPart(spec->line))) {
appendLineStringBuf(sb, spec->line);
if (readLine(spec, STRIP_NOTHING) > 0) {
nextPart = PART_NONE;
break;
}
}
res = addChangelog(spec->packages->header, sb);
freeStringBuf(sb);
return (res) ? res : nextPart;
}
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 */
SKIPSPACE(s);
while (*s) {
if (*s != '*') {
rpmError(RPMERR_BADSPEC, "%%changelog entries must start with *");
return RPMERR_BADSPEC;
}
/* find end of line */
date = s;
SKIPTONEWLINE(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++) {
SKIPSPACE(s);
SKIPNONSPACE(s);
}
SKIPSPACE(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 */
SKIPSPACE(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 */
SKIPSPACE(text);
if (! *text) {
rpmError(RPMERR_BADSPEC, "no description in %%changelog");
return RPMERR_BADSPEC;
}
/* find the next leading '*' (or eos) */
s = text;
do {
s++;
} while (*s && (*(s-1) != '\n' || *s != '*'));
next = s;
s--;
/* backup to end of description */
while ((s > text) && isspace(*s)) {
*s-- = '\0';
}
addChangelogEntry(h, time, name, text);
s = next;
}
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);
}
}
/* 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 };
static char lengths[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
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;
/* make this noon so the day is always right (as we make this UTC) */
time.tm_hour = 12;
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;
}

110
build/parseDescription.c Normal file
View File

@ -0,0 +1,110 @@
#include <malloc.h>
#include "spec.h"
#include "header.h"
#include "read.h"
#include "part.h"
#include "misc.h"
#include "rpmlib.h"
#include "package.h"
#include "popt/popt.h"
int parseDescription(Spec spec)
{
int nextPart;
StringBuf sb;
char *name = NULL;
char *lang = RPMBUILD_DEFAULT_LANG;
int flag = PART_SUBNAME;
Package pkg;
int rc, argc;
char arg, **argv = NULL;
poptContext optCon = NULL;
struct poptOption optionsTable[] = {
{ NULL, 'n', POPT_ARG_STRING, &name, 'n' },
{ NULL, 'l', POPT_ARG_STRING, &lang, 'l' },
{ 0, 0, 0, 0, 0 }
};
if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
rpmError(RPMERR_BADSPEC, "line %d: Error parsing %%description: %s",
spec->lineNum, poptStrerror(rc));
return RPMERR_BADSPEC;
}
optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
while ((arg = poptGetNextOpt(optCon)) > 0) {
if (arg == 'n') {
flag = PART_NAME;
}
}
if (arg < -1) {
rpmError(RPMERR_BADSPEC, "line %d: Bad option %s: %s",
spec->lineNum,
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
if (poptPeekArg(optCon)) {
if (! name) {
name = poptGetArg(optCon);
}
if (poptPeekArg(optCon)) {
rpmError(RPMERR_BADSPEC, "line %d: Too many names: %s",
spec->lineNum,
spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
}
if (lookupPackage(spec, name, flag, &pkg)) {
rpmError(RPMERR_BADSPEC, "line %d: Package does not exist: %s",
spec->lineNum, spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
/******************/
#if 0
if (headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) {
rpmError(RPMERR_BADSPEC, "line %d: Second description", spec->lineNum);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
#endif
sb = newStringBuf();
if (readLine(spec, STRIP_TRAILINGSPACE) > 0) {
nextPart = PART_NONE;
} else {
while (! (nextPart = isPart(spec->line))) {
appendLineStringBuf(sb, spec->line);
if (readLine(spec, STRIP_TRAILINGSPACE) > 0) {
nextPart = PART_NONE;
break;
}
}
}
stripTrailingBlanksStringBuf(sb);
headerAddI18NString(pkg->header, RPMTAG_DESCRIPTION,
getStringBuf(sb), lang);
freeStringBuf(sb);
FREE(argv);
poptFreeContext(optCon);
return nextPart;
}

103
build/parseFiles.c Normal file
View File

@ -0,0 +1,103 @@
#include <string.h>
#include <malloc.h>
#include "header.h"
#include "read.h"
#include "part.h"
#include "misc.h"
#include "rpmlib.h"
#include "package.h"
#include "stringbuf.h"
#include "popt/popt.h"
int parseFiles(Spec spec)
{
int nextPart;
Package pkg;
char *name = NULL;
char *file = NULL;
int rc, argc;
char arg, **argv = NULL;
int flag = PART_SUBNAME;
poptContext optCon = NULL;
struct poptOption optionsTable[] = {
{ NULL, 'n', POPT_ARG_STRING, &name, 'n' },
{ NULL, 'f', POPT_ARG_STRING, &file, 'f' },
{ 0, 0, 0, 0, 0 }
};
if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
rpmError(RPMERR_BADSPEC, "line %d: Error parsing %%files: %s",
spec->lineNum, poptStrerror(rc));
return RPMERR_BADSPEC;
}
optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
while ((arg = poptGetNextOpt(optCon)) > 0) {
if (arg == 'n') {
flag = PART_NAME;
}
}
if (arg < -1) {
rpmError(RPMERR_BADSPEC, "line %d: Bad option %s: %s",
spec->lineNum,
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
if (poptPeekArg(optCon)) {
if (! name) {
name = poptGetArg(optCon);
}
if (poptPeekArg(optCon)) {
rpmError(RPMERR_BADSPEC, "line %d: Too many names: %s",
spec->lineNum,
spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
}
if (lookupPackage(spec, name, flag, &pkg)) {
rpmError(RPMERR_BADSPEC, "line %d: Package does not exist: %s",
spec->lineNum, spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
if (pkg->fileList) {
rpmError(RPMERR_BADSPEC, "line %d: Second %%files list",
spec->lineNum);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
if (file) {
pkg->fileFile = strdup(file);
}
pkg->fileList = newStringBuf();
if (readLine(spec, STRIP_NOTHING) > 0) {
nextPart = PART_NONE;
} else {
while (! (nextPart = isPart(spec->line))) {
appendLineStringBuf(pkg->fileList, spec->line);
if (readLine(spec, STRIP_NOTHING) > 0) {
nextPart = PART_NONE;
break;
}
}
}
FREE(argv);
poptFreeContext(optCon);
return nextPart;
}

631
build/parsePreamble.c Normal file
View File

@ -0,0 +1,631 @@
#include <string.h>
#include <malloc.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "read.h"
#include "part.h"
#include "rpmlib.h"
#include "spec.h"
#include "package.h"
#include "misc.h"
#include "reqprov.h"
#include "parse.h"
#include "popt/popt.h"
static int copyTags[] = {
RPMTAG_VERSION,
RPMTAG_RELEASE,
RPMTAG_COPYRIGHT,
RPMTAG_PACKAGER,
RPMTAG_DISTRIBUTION,
RPMTAG_VENDOR,
RPMTAG_ICON,
0
};
static int requiredTags[] = {
RPMTAG_NAME,
RPMTAG_VERSION,
RPMTAG_RELEASE,
RPMTAG_SUMMARY,
RPMTAG_GROUP,
RPMTAG_COPYRIGHT,
RPMTAG_PACKAGER,
RPMTAG_DISTRIBUTION,
RPMTAG_VENDOR,
0
};
static int handlePreambleTag(Spec spec, Package pkg, int tag, char *macro,
char *lang);
static void initPreambleList(void);
static int findPreambleTag(Spec spec, int *tag, char **macro, char *lang);
static int checkForRequired(Header h, char *name);
static void copyFromMain(Spec spec, Package pkg);
static int checkForDuplicates(Header h, char *name);
static void fillOutMainPackage(Header h);
static char *tagName(int tag);
static int checkForValidArchitectures(Spec spec);
static int isMemberInEntry(Header header, char *name, int tag);
static int readIcon(Header h, char *file);
int parsePreamble(Spec spec, int initialPackage)
{
int nextPart;
int tag;
char *name, *mainName, *linep, *macro;
int flag;
Package pkg;
char fullName[BUFSIZ];
char lang[BUFSIZ];
strcpy(fullName, "(main package)");
pkg = newPackage(spec);
if (! initialPackage) {
/* There is one option to %package: <pkg> or -n <pkg> */
if (parseSimplePart(spec->line, &name, &flag)) {
rpmError(RPMERR_BADSPEC, "Bad package specification: %s",
spec->line);
return RPMERR_BADSPEC;
}
if (!lookupPackage(spec, name, flag, NULL)) {
rpmError(RPMERR_BADSPEC, "Package already exists: %s", spec->line);
return RPMERR_BADSPEC;
}
/* Construct the package */
if (flag == PART_SUBNAME) {
headerGetEntry(spec->packages->header, RPMTAG_NAME,
NULL, (void *) &mainName, NULL);
sprintf(fullName, "%s-%s", mainName, name);
} else {
strcpy(fullName, name);
}
headerAddEntry(pkg->header, RPMTAG_NAME, RPM_STRING_TYPE, fullName, 1);
}
if (readLine(spec, STRIP_TRAILINGSPACE) > 0) {
nextPart = PART_NONE;
} else {
while (! (nextPart = isPart(spec->line))) {
/* Skip blank lines */
linep = spec->line;
SKIPSPACE(linep);
if (*linep) {
if (findPreambleTag(spec, &tag, &macro, lang)) {
rpmError(RPMERR_BADSPEC, "line %d: Unknown tag: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
if (handlePreambleTag(spec, pkg, tag, macro, lang)) {
return RPMERR_BADSPEC;
}
if (spec->buildArchitectures && !spec->inBuildArchitectures) {
return PART_BUILDARCHITECTURES;
}
}
if (readLine(spec, STRIP_TRAILINGSPACE) > 0) {
nextPart = PART_NONE;
break;
}
}
}
/* Do some final processing on the header */
if (!spec->gotBuildRoot && spec->buildRoot) {
rpmError(RPMERR_BADSPEC, "Spec file can't use BuildRoot");
return RPMERR_BADSPEC;
}
if (checkForValidArchitectures(spec)) {
return RPMERR_BADSPEC;
}
if (pkg == spec->packages) {
fillOutMainPackage(pkg->header);
}
if (checkForDuplicates(pkg->header, fullName)) {
return RPMERR_BADSPEC;
}
if (pkg != spec->packages) {
copyFromMain(spec, pkg);
}
if (checkForRequired(pkg->header, fullName)) {
return RPMERR_BADSPEC;
}
return nextPart;
}
static int isMemberInEntry(Header header, char *name, int tag)
{
char **names;
int count;
if (headerGetEntry(header, tag, NULL, (void **)&names, &count)) {
while (count--) {
if (!strcmp(names[count], name)) {
FREE(names);
return 1;
}
}
FREE(names);
return 0;
}
return -1;
}
static int checkForValidArchitectures(Spec spec)
{
char *arch, *os;
rpmGetArchInfo(&arch, NULL);
rpmGetOsInfo(&os, NULL);
if (isMemberInEntry(spec->buildRestrictions,
arch, RPMTAG_EXCLUDEARCH) == 1) {
rpmError(RPMERR_BADSPEC, "Architecture is excluded: %s", arch);
return RPMERR_BADSPEC;
}
if (isMemberInEntry(spec->buildRestrictions,
arch, RPMTAG_EXCLUSIVEARCH) == 0) {
rpmError(RPMERR_BADSPEC, "Architecture is not included: %s", arch);
return RPMERR_BADSPEC;
}
if (isMemberInEntry(spec->buildRestrictions,
os, RPMTAG_EXCLUDEOS) == 1) {
rpmError(RPMERR_BADSPEC, "OS is excluded: %s", os);
return RPMERR_BADSPEC;
}
if (isMemberInEntry(spec->buildRestrictions,
os, RPMTAG_EXCLUSIVEOS) == 0) {
rpmError(RPMERR_BADSPEC, "OS is not included: %s", os);
return RPMERR_BADSPEC;
}
return 0;
}
static int checkForRequired(Header h, char *name)
{
int res = 0;
int *p = requiredTags;
while (*p) {
if (!headerIsEntry(h, *p)) {
rpmError(RPMERR_BADSPEC, "%s field must be present in package: %s",
tagName(*p), name);
res = 1;
}
p++;
}
return res;
}
static void copyFromMain(Spec spec, Package pkg)
{
Header headerFrom, headerTo;
int *p = copyTags;
char *s;
int type, count;
headerFrom = spec->packages->header;
headerTo = pkg->header;
while (*p) {
if (!headerIsEntry(headerTo, *p)) {
if (headerGetEntry(headerFrom, *p, &type, (void **) &s, &count)) {
headerAddEntry(headerTo, *p, type, s, count);
if (type == RPM_STRING_ARRAY_TYPE) {
FREE(s);
}
}
}
p++;
}
}
static int checkForDuplicates(Header h, char *name)
{
int res = 0;
int lastTag, tag;
HeaderIterator hi;
headerSort(h);
hi = headerInitIterator(h);
lastTag = 0;
while (headerNextIterator(hi, &tag, NULL, NULL, NULL)) {
if (tag == lastTag) {
rpmError(RPMERR_BADSPEC, "Duplicate %s entries in package: %s",
tagName(tag), name);
res = 1;
}
lastTag = tag;
}
headerFreeIterator(hi);
return res;
}
static void fillOutMainPackage(Header h)
{
if (!headerIsEntry(h, RPMTAG_VENDOR)) {
if (rpmGetVar(RPMVAR_VENDOR)) {
headerAddEntry(h, RPMTAG_VENDOR, RPM_STRING_TYPE,
rpmGetVar(RPMVAR_VENDOR), 1);
}
}
if (!headerIsEntry(h, RPMTAG_PACKAGER)) {
if (rpmGetVar(RPMVAR_PACKAGER)) {
headerAddEntry(h, RPMTAG_PACKAGER, RPM_STRING_TYPE,
rpmGetVar(RPMVAR_PACKAGER), 1);
}
}
if (!headerIsEntry(h, RPMTAG_DISTRIBUTION)) {
if (rpmGetVar(RPMVAR_DISTRIBUTION)) {
headerAddEntry(h, RPMTAG_DISTRIBUTION, RPM_STRING_TYPE,
rpmGetVar(RPMVAR_DISTRIBUTION), 1);
}
}
}
#define SINGLE_TOKEN_ONLY \
if (multiToken) { \
rpmError(RPMERR_BADSPEC, "line %d: Tag takes single token only: %s", \
spec->lineNum, spec->line); \
return RPMERR_BADSPEC; \
}
static int handlePreambleTag(Spec spec, Package pkg, int tag, char *macro,
char *lang)
{
char *field = spec->line;
char *end;
int multiToken = 0;
int num, rc;
/* Find the start of the "field" and strip trailing space */
while ((*field) && (*field != ':')) {
field++;
}
if (*field != ':') {
rpmError(RPMERR_BADSPEC, "line %d: Malformed tag: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
field++;
SKIPSPACE(field);
if (! *field) {
/* Empty field */
rpmError(RPMERR_BADSPEC, "line %d: Empty tag: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
end = findLastChar(field);
*(end+1) = '\0';
/* See if this is multi-token */
end = field;
SKIPNONSPACE(end);
if (*end) {
multiToken = 1;
}
if (macro) {
addMacro(&spec->macros, macro, field);
}
switch (tag) {
case RPMTAG_NAME:
case RPMTAG_VERSION:
case RPMTAG_RELEASE:
case RPMTAG_GROUP:
case RPMTAG_URL:
SINGLE_TOKEN_ONLY;
/* These are for backward compatibility */
if (tag == RPMTAG_VERSION) {
addMacro(&spec->macros, "PACKAGE_VERSION", field);
} else if (tag == RPMTAG_RELEASE) {
addMacro(&spec->macros, "PACKAGE_RELEASE", field);
}
/* fall through */
case RPMTAG_SUMMARY:
case RPMTAG_DISTRIBUTION:
case RPMTAG_VENDOR:
case RPMTAG_COPYRIGHT:
case RPMTAG_PACKAGER:
if (! *lang) {
headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, field, 1);
} else {
headerAddI18NString(pkg->header, tag, field, lang);
}
break;
case RPMTAG_BUILDROOT:
SINGLE_TOKEN_ONLY;
if (! spec->buildRoot) {
if (rpmGetVar(RPMVAR_BUILDROOT)) {
spec->buildRoot = strdup(rpmGetVar(RPMVAR_BUILDROOT));
} else {
spec->buildRoot = strdup(field);
}
}
if (!strcmp(spec->buildRoot, "/")) {
rpmError(RPMERR_BADSPEC,
"line %d: BuildRoot can not be \"/\": %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
spec->gotBuildRoot = 1;
break;
case RPMTAG_DEFAULTPREFIX:
SINGLE_TOKEN_ONLY;
if (field[0] != '/') {
rpmError(RPMERR_BADSPEC,
"line %d: Prefix must begin with '/': %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, field, 1);
break;
case RPMTAG_DOCDIR:
SINGLE_TOKEN_ONLY;
FREE(spec->docDir);
if (field[0] != '/') {
rpmError(RPMERR_BADSPEC,
"line %d: Docdir must begin with '/': %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
spec->docDir = strdup(field);
break;
case RPMTAG_SERIAL:
SINGLE_TOKEN_ONLY;
if (parseNum(field, &num)) {
rpmError(RPMERR_BADSPEC,
"line %d: Serial field must be a number: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
headerAddEntry(pkg->header, tag, RPM_INT32_TYPE, &num, 1);
break;
case RPMTAG_AUTOREQPROV:
spec->autoReqProv = parseYesNo(field);
break;
case RPMTAG_SOURCE:
case RPMTAG_PATCH:
SINGLE_TOKEN_ONLY;
if ((rc = addSource(spec, pkg, field, tag))) {
return rc;
}
break;
case RPMTAG_ICON:
SINGLE_TOKEN_ONLY;
if ((rc = addSource(spec, pkg, field, tag))) {
return rc;
}
if ((rc = readIcon(pkg->header, field))) {
return RPMERR_BADSPEC;
}
break;
case RPMTAG_NOSOURCE:
case RPMTAG_NOPATCH:
spec->noSource = 1;
if ((rc = parseNoSource(spec, field, tag))) {
return rc;
}
break;
case RPMTAG_OBSOLETES:
case RPMTAG_PROVIDES:
if ((rc = parseProvidesObsoletes(spec, pkg, field, tag))) {
return rc;
}
break;
case RPMTAG_REQUIREFLAGS:
case RPMTAG_CONFLICTFLAGS:
case RPMTAG_PREREQ:
if ((rc = parseRequiresConflicts(spec, pkg, field, tag))) {
return rc;
}
break;
case RPMTAG_EXCLUDEARCH:
case RPMTAG_EXCLUSIVEARCH:
case RPMTAG_EXCLUDEOS:
case RPMTAG_EXCLUSIVEOS:
addOrAppendListEntry(spec->buildRestrictions, tag, field);
break;
case RPMTAG_BUILDARCHS:
if ((rc = poptParseArgvString(field,
&(spec->buildArchitectureCount),
&(spec->buildArchitectures)))) {
rpmError(RPMERR_BADSPEC,
"line %d: Bad BuildArchitecture format: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
if (! spec->buildArchitectureCount) {
FREE(spec->buildArchitectures);
}
break;
default:
rpmError(RPMERR_INTERNAL, "Internal error: Bogus tag %d", tag);
return RPMERR_INTERNAL;
}
return 0;
}
static struct PreambleRec {
int tag;
int len;
int multiLang;
char *token;
} preambleList[] = {
{RPMTAG_NAME, 0, 0, "name"},
{RPMTAG_VERSION, 0, 0, "version"},
{RPMTAG_RELEASE, 0, 0, "release"},
{RPMTAG_SERIAL, 0, 0, "serial"},
/* {RPMTAG_DESCRIPTION, 0, "description"}, */
{RPMTAG_SUMMARY, 0, 1, "summary"},
{RPMTAG_COPYRIGHT, 0, 0, "copyright"},
{RPMTAG_COPYRIGHT, 0, 0, "license"},
{RPMTAG_DISTRIBUTION, 0, 0, "distribution"},
{RPMTAG_VENDOR, 0, 0, "vendor"},
{RPMTAG_GROUP, 0, 0, "group"},
{RPMTAG_PACKAGER, 0, 0, "packager"},
{RPMTAG_URL, 0, 0, "url"},
/* {RPMTAG_ROOT, 0, "root"}, */
{RPMTAG_SOURCE, 0, 0, "source"},
{RPMTAG_PATCH, 0, 0, "patch"},
{RPMTAG_NOSOURCE, 0, 0, "nosource"},
{RPMTAG_NOPATCH, 0, 0, "nopatch"},
{RPMTAG_EXCLUDEARCH, 0, 0, "excludearch"},
{RPMTAG_EXCLUSIVEARCH, 0, 0, "exclusivearch"},
{RPMTAG_EXCLUDEOS, 0, 0, "excludeos"},
{RPMTAG_EXCLUSIVEOS, 0, 0, "exclusiveos"},
/* {RPMTAG_EXCLUDE, 0, "exclude"}, */
/* {RPMTAG_EXCLUSIVE, 0, "exclusive"}, */
{RPMTAG_ICON, 0, 0, "icon"},
{RPMTAG_PROVIDES, 0, 0, "provides"},
{RPMTAG_REQUIREFLAGS, 0, 0, "requires"},
{RPMTAG_PREREQ, 0, 0, "prereq"},
{RPMTAG_CONFLICTFLAGS, 0, 0, "conflicts"},
{RPMTAG_OBSOLETES, 0, 0, "obsoletes"},
{RPMTAG_DEFAULTPREFIX, 0, 0, "prefix"},
{RPMTAG_BUILDROOT, 0, 0, "buildroot"},
{RPMTAG_BUILDARCHS, 0, 0, "buildarchitectures"},
{RPMTAG_AUTOREQPROV, 0, 0, "autoreqprov"},
{RPMTAG_DOCDIR, 0, 0, "docdir"},
{0, 0, 0, 0}
};
static void initPreambleList(void)
{
struct PreambleRec *p = preambleList;
while (p->token) {
p->len = strlen(p->token);
p++;
}
}
static int findPreambleTag(Spec spec, int *tag, char **macro, char *lang)
{
char *s;
struct PreambleRec *p = preambleList;
if (! p->len) {
initPreambleList();
}
while (p->token && strncasecmp(spec->line, p->token, p->len)) {
p++;
}
if (!p->token) {
return 1;
}
s = spec->line + p->len;
SKIPSPACE(s);
if (! p->multiLang) {
/* Unless this is a source or a patch, a ':' better be next */
if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) {
if (*s != ':') {
return 1;
}
}
*lang = '\0';
} else {
if (*s != ':') {
if (*s != '(') return 1;
s++;
SKIPSPACE(s);
while (! isspace(*s) && *s != ')') {
*lang++ = *s++;
}
*lang = '\0';
SKIPSPACE(s);
if (*s != ')') return 1;
s++;
SKIPSPACE(s);
if (*s != ':') return 1;
} else {
strcpy(lang, RPMBUILD_DEFAULT_LANG);
}
}
*tag = p->tag;
if (macro) {
*macro = p->token;
}
return 0;
}
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 readIcon(Header h, char *file)
{
char buf[BUFSIZ], *icon;
struct stat statbuf;
int fd;
sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), file);
if (stat(buf, &statbuf)) {
rpmError(RPMERR_BADSPEC, "Unable to read icon: %s", file);
return RPMERR_BADSPEC;
}
icon = malloc(statbuf.st_size);
fd = open(buf, O_RDONLY);
if (read(fd, icon, statbuf.st_size) != statbuf.st_size) {
close(fd);
rpmError(RPMERR_BADSPEC, "Unable to read icon: %s", file);
return RPMERR_BADSPEC;
}
close(fd);
if (! strncmp(icon, "GIF", 3)) {
headerAddEntry(h, RPMTAG_GIF, RPM_BIN_TYPE, icon, statbuf.st_size);
} else if (! strncmp(icon, "/* XPM", 6)) {
headerAddEntry(h, RPMTAG_XPM, RPM_BIN_TYPE, icon, statbuf.st_size);
} else {
rpmError(RPMERR_BADSPEC, "Unknown icon type: %s", file);
return RPMERR_BADSPEC;
}
free(icon);
return 0;
}

480
build/parsePrep.c Normal file
View File

@ -0,0 +1,480 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include "spec.h"
#include "read.h"
#include "part.h"
#include "rpmlib.h"
#include "lib/misc.h"
#include "popt/popt.h"
#include "names.h"
#include "misc.h"
#include "config.h"
static int doSetupMacro(Spec spec, char *line);
static int doPatchMacro(Spec spec, char *line);
static char *doPatch(Spec spec, int c, int strip, char *db,
int reverse, int removeEmpties);
static int isCompressed(char *file, int *compressed);
static int checkOwners(char *file);
static char *doUntar(Spec spec, int c, int quietly);
int parsePrep(Spec spec)
{
int nextPart, res;
StringBuf buf;
char **lines, **saveLines;
if (spec->prep) {
rpmError(RPMERR_BADSPEC, "line %d: second %%prep", spec->lineNum);
return RPMERR_BADSPEC;
}
spec->prep = newStringBuf();
buf = newStringBuf();
/* There are no options to %prep */
if (readLine(spec, STRIP_NOTHING) > 0) {
return PART_NONE;
}
while (! (nextPart = isPart(spec->line))) {
/* Need to expand the macros inline. That way we */
/* can give good line number information on error. */
appendLineStringBuf(buf, spec->line);
if (readLine(spec, STRIP_NOTHING) > 0) {
nextPart = PART_NONE;
break;
}
}
lines = splitString(getStringBuf(buf), strlen(getStringBuf(buf)), '\n');
saveLines = lines;
while (*lines) {
res = 0;
if (! strncmp(*lines, "%setup", 6)) {
res = doSetupMacro(spec, *lines);
} else if (! strncmp(*lines, "%patch", 6)) {
res = doPatchMacro(spec, *lines);
} else {
appendLineStringBuf(spec->prep, *lines);
}
if (res) {
freeSplitString(saveLines);
return res;
}
lines++;
}
freeSplitString(saveLines);
return nextPart;
}
static int doSetupMacro(Spec spec, char *line)
{
char *version, *name;
int leaveDirs = 0, skipDefaultAction = 0;
int createDir = 0, quietly = 0;
char * dirName = NULL;
char buf[BUFSIZ];
StringBuf before;
StringBuf after;
poptContext optCon;
int argc;
char ** argv;
int arg;
char * optArg;
char * chptr;
int rc;
int num;
struct poptOption optionsTable[] = {
{ NULL, 'a', POPT_ARG_STRING, NULL, 'a' },
{ NULL, 'b', POPT_ARG_STRING, NULL, 'b' },
{ NULL, 'c', 0, &createDir, 0 },
{ NULL, 'D', 0, &leaveDirs, 0 },
{ NULL, 'n', POPT_ARG_STRING, &dirName, 0 },
{ NULL, 'T', 0, &skipDefaultAction, 0 },
{ NULL, 'q', 0, &quietly, 0 },
{ 0, 0, 0, 0, 0 }
};
if ((rc = poptParseArgvString(line, &argc, &argv))) {
rpmError(RPMERR_BADSPEC, "Error parsing %%setup: %s",
poptStrerror(rc));
return RPMERR_BADSPEC;
}
before = newStringBuf();
after = newStringBuf();
optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
while ((arg = poptGetNextOpt(optCon)) > 0) {
optArg = poptGetOptArg(optCon);
/* We only parse -a and -b here */
if (parseNum(optArg, &num)) {
rpmError(RPMERR_BADSPEC, "line %d: Bad arg to %%setup %c: %s",
spec->lineNum, num, optArg);
free(argv);
freeStringBuf(before);
freeStringBuf(after);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
chptr = doUntar(spec, num, quietly);
if (!chptr) {
return RPMERR_BADSPEC;
}
if (arg == 'a')
appendLineStringBuf(after, chptr);
else
appendLineStringBuf(before, chptr);
}
if (arg < -1) {
rpmError(RPMERR_BADSPEC, "line %d: Bad %%setup option %s: %s",
spec->lineNum,
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(arg));
free(argv);
freeStringBuf(before);
freeStringBuf(after);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
if (dirName) {
spec->buildSubdir = strdup(dirName);
} else {
headerGetEntry(spec->packages->header, RPMTAG_VERSION, NULL,
(void *) &version, NULL);
headerGetEntry(spec->packages->header, RPMTAG_NAME, NULL,
(void *) &name, NULL);
sprintf(buf, "%s-%s", name, version);
spec->buildSubdir = strdup(buf);
}
free(argv);
poptFreeContext(optCon);
/* cd to the build dir */
sprintf(buf, "cd %s", rpmGetVar(RPMVAR_BUILDDIR));
appendLineStringBuf(spec->prep, buf);
/* delete any old sources */
if (!leaveDirs) {
sprintf(buf, "rm -rf %s", spec->buildSubdir);
appendLineStringBuf(spec->prep, buf);
}
/* if necessary, create and cd into the proper dir */
if (createDir) {
sprintf(buf, "mkdir -p %s\ncd %s",
spec->buildSubdir, spec->buildSubdir);
appendLineStringBuf(spec->prep, buf);
}
/* do the default action */
if (!createDir && !skipDefaultAction) {
chptr = doUntar(spec, 0, quietly);
if (!chptr) {
return RPMERR_BADSPEC;
}
appendLineStringBuf(spec->prep, chptr);
}
appendStringBuf(spec->prep, getStringBuf(before));
freeStringBuf(before);
if (!createDir) {
sprintf(buf, "cd %s", spec->buildSubdir);
appendLineStringBuf(spec->prep, buf);
}
if (createDir && !skipDefaultAction) {
chptr = doUntar(spec, 0, quietly);
if (!chptr) {
return RPMERR_BADSPEC;
}
appendLineStringBuf(spec->prep, chptr);
}
appendStringBuf(spec->prep, getStringBuf(after));
freeStringBuf(after);
/* clean up permissions etc */
if (!geteuid()) {
appendLineStringBuf(spec->prep, "chown -R root .");
appendLineStringBuf(spec->prep, "chgrp -R root .");
}
if (rpmGetVar(RPMVAR_FIXPERMS)) {
appendStringBuf(spec->prep, "chmod -R ");
appendStringBuf(spec->prep, rpmGetVar(RPMVAR_FIXPERMS));
appendLineStringBuf(spec->prep, " .");
}
return 0;
}
static char *doUntar(Spec spec, int c, int quietly)
{
static char buf[BUFSIZ];
char file[BUFSIZ];
char *s, *taropts;
struct Source *sp;
int compressed;
s = NULL;
sp = spec->sources;
while (sp) {
if ((sp->flags & RPMBUILD_ISSOURCE) && (sp->num == c)) {
s = sp->source;
break;
}
sp = sp->next;
}
if (! s) {
rpmError(RPMERR_BADSPEC, "No source number %d", c);
return NULL;
}
sprintf(file, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), s);
taropts = (rpmIsVerbose() && !quietly ? "-xvvf" : "-xf");
if (isCompressed(file, &compressed)) {
return NULL;
}
if (checkOwners(file)) {
return NULL;
}
if (compressed) {
sprintf(buf,
"%s -dc %s | tar %s -\n"
"if [ $? -ne 0 ]; then\n"
" exit $?\n"
"fi",
rpmGetVar(RPMVAR_GZIPBIN), file, taropts);
} else {
sprintf(buf, "tar %s %s", taropts, file);
}
return buf;
}
static int doPatchMacro(Spec spec, char *line)
{
char *opt_b;
int opt_P, opt_p, opt_R, opt_E;
char *s;
char buf[BUFSIZ];
int patch_nums[1024]; /* XXX - we can only handle 1024 patches! */
int patch_index, x;
opt_P = opt_p = opt_R = opt_E = 0;
opt_b = NULL;
patch_index = 0;
if (! strchr(" \t\n", line[6])) {
/* %patchN */
sprintf(buf, "%%patch -P %s", line + 6);
} else {
strcpy(buf, line);
}
strtok(buf, " \t\n"); /* remove %patch */
while ((s = strtok(NULL, " \t\n"))) {
if (!strcmp(s, "-P")) {
opt_P = 1;
} else if (!strcmp(s, "-R")) {
opt_R = 1;
} else if (!strcmp(s, "-E")) {
opt_E = 1;
} else if (!strcmp(s, "-b")) {
/* orig suffix */
opt_b = strtok(NULL, " \t\n");
if (! opt_b) {
rpmError(RPMERR_BADSPEC, "line %d: Need arg to %%patch -b: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
} else if (!strcmp(s, "-z")) {
/* orig suffix */
opt_b = strtok(NULL, " \t\n");
if (! opt_b) {
rpmError(RPMERR_BADSPEC, "line %d: Need arg to %%patch -z: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
} else if (!strncmp(s, "-p", 2)) {
/* unfortunately, we must support -pX */
if (! strchr(" \t\n", s[2])) {
s = s + 2;
} else {
s = strtok(NULL, " \t\n");
if (! s) {
rpmError(RPMERR_BADSPEC,
"line %d: Need arg to %%patch -p: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
}
if (parseNum(s, &opt_p)) {
rpmError(RPMERR_BADSPEC, "line %d: Bad arg to %%patch -p: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
} else {
/* Must be a patch num */
if (patch_index == 1024) {
rpmError(RPMERR_BADSPEC, "Too many patches!");
return RPMERR_BADSPEC;
}
if (parseNum(s, &(patch_nums[patch_index]))) {
rpmError(RPMERR_BADSPEC, "line %d: Bad arg to %%patch: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
patch_index++;
}
}
/* All args processed */
if (! opt_P) {
s = doPatch(spec, 0, opt_p, opt_b, opt_R, opt_E);
if (! s) {
return RPMERR_BADSPEC;
}
appendLineStringBuf(spec->prep, s);
}
x = 0;
while (x < patch_index) {
s = doPatch(spec, patch_nums[x], opt_p, opt_b, opt_R, opt_E);
if (! s) {
return RPMERR_BADSPEC;
}
appendLineStringBuf(spec->prep, s);
x++;
}
return 0;
}
static char *doPatch(Spec spec, int c, int strip, char *db,
int reverse, int removeEmpties)
{
static char buf[BUFSIZ];
char file[BUFSIZ];
char args[BUFSIZ];
char *s;
struct Source *sp;
int compressed;
s = NULL;
sp = spec->sources;
while (sp) {
if ((sp->flags & RPMBUILD_ISPATCH) && (sp->num == c)) {
s = sp->source;
break;
}
sp = sp->next;
}
if (! s) {
rpmError(RPMERR_BADSPEC, "No patch number %d", c);
return NULL;
}
sprintf(file, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), s);
args[0] = '\0';
if (db) {
#if HAVE_OLDPATCH_21 == 0
strcat(args, "-b ");
#endif
strcat(args, "--suffix ");
strcat(args, db);
}
if (reverse) {
strcat(args, " -R");
}
if (removeEmpties) {
strcat(args, " -E");
}
if (isCompressed(file, &compressed)) {
return NULL;
}
if (checkOwners(file)) {
return NULL;
}
if (compressed) {
sprintf(buf,
"echo \"Patch #%d:\"\n"
"%s -dc %s | patch -p%d %s -s\n"
"if [ $? -ne 0 ]; then\n"
" exit $?\n"
"fi",
c, rpmGetVar(RPMVAR_GZIPBIN), file, strip, args);
} else {
sprintf(buf,
"echo \"Patch #%d:\"\n"
"patch -p%d %s -s < %s", c, strip, args, file);
}
return buf;
}
static int checkOwners(char *file)
{
struct stat sb;
if (lstat(file, &sb)) {
rpmError(RPMERR_BADSPEC, "Bad source: %s: %s", file, strerror(errno));
return RPMERR_BADSPEC;
}
if (!getUname(sb.st_uid) || !getGname(sb.st_gid)) {
rpmError(RPMERR_BADSPEC, "Bad owner/group: %s", file);
return RPMERR_BADSPEC;
}
return 0;
}
static int isCompressed(char *file, int *compressed)
{
int fd;
unsigned char magic[4];
*compressed = 0;
if (!(fd = open(file, O_RDONLY))) {
return 1;
}
if (! read(fd, magic, 4)) {
return 1;
}
close(fd);
if (((magic[0] == 0037) && (magic[1] == 0213)) || /* gzip */
((magic[0] == 0037) && (magic[1] == 0236)) || /* old gzip */
((magic[0] == 0037) && (magic[1] == 0036)) || /* pack */
((magic[0] == 0037) && (magic[1] == 0240)) || /* SCO lzh */
((magic[0] == 0037) && (magic[1] == 0235)) || /* compress */
((magic[0] == 0120) && (magic[1] == 0113) &&
(magic[2] == 0003) && (magic[3] == 0004)) /* pkzip */
) {
*compressed = 1;
}
return 0;
}

125
build/parseReqs.c Normal file
View File

@ -0,0 +1,125 @@
#include <string.h>
#include "spec.h"
#include "rpmlib.h"
#include "reqprov.h"
static struct ReqComp {
char *token;
int sense;
} ReqComparisons[] = {
{ "<=", 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},
{ ">=", 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},
{ NULL, 0 },
};
int parseRequiresConflicts(Spec spec, Package pkg, char *field, int tag)
{
char buf[BUFSIZ], *bufp, *version, *name;
int flags;
char *req = NULL;
struct ReqComp *rc;
strcpy(buf, field);
bufp = buf;
while (req || (req = strtok(bufp, " ,\t\n"))) {
bufp = NULL;
if (tag == RPMTAG_CONFLICTFLAGS) {
if (req[0] == '/') {
rpmError(RPMERR_BADSPEC,
"line %d: No file names in Conflicts: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
flags = RPMSENSE_CONFLICTS;
name = "Conflicts";
} else if (tag == RPMTAG_PREREQ) {
flags = RPMSENSE_PREREQ;
name = "PreReq";
} else {
flags = RPMSENSE_ANY;
name = "Requires";
}
if ((version = strtok(NULL, " ,\t\n"))) {
rc = ReqComparisons;
while (rc->token && strcmp(version, rc->token)) {
rc++;
}
if (rc->token) {
if (req[0] == '/') {
rpmError(RPMERR_BADSPEC,
"line %d: No versions on file names in %s: %s",
spec->lineNum, name, spec->line);
return RPMERR_BADSPEC;
}
if (tag == RPMTAG_PREREQ) {
rpmError(RPMERR_BADSPEC,
"line %d: No versions in PreReq: %s",
spec->lineNum, spec->line);
return RPMERR_BADSPEC;
}
/* read a version */
flags |= rc->sense;
version = strtok(NULL, " ,\t\n");
}
}
if ((flags & RPMSENSE_SENSEMASK) && !version) {
rpmError(RPMERR_BADSPEC,
"line %d: Version required in %s: %s",
spec->lineNum, name, spec->line);
return RPMERR_BADSPEC;
}
addReqProv(spec, pkg, flags, req,
(flags & RPMSENSE_SENSEMASK) ? version : NULL);
/* If there is no sense, we just read the next token */
req = (flags & RPMSENSE_SENSEMASK) ? NULL : version;
}
return 0;
}
int parseProvidesObsoletes(Spec spec, Package pkg, char *field, int tag)
{
char *prov, buf[BUFSIZ], *line;
int flags;
flags = (tag == RPMTAG_PROVIDES) ? RPMSENSE_PROVIDES : RPMSENSE_OBSOLETES;
strcpy(buf, field);
line = buf;
while ((prov = strtok(line, " ,\t\n"))) {
if (prov[0] == '/') {
rpmError(RPMERR_BADSPEC,
"line %d: No file names in %s: %s",
spec->lineNum,
(tag == RPMTAG_PROVIDES) ? "Provides" : "Obsoletes",
spec->line);
return RPMERR_BADSPEC;
}
addReqProv(spec, pkg, flags, prov, NULL);
line = NULL;
}
return 0;
}

199
build/parseScript.c Normal file
View File

@ -0,0 +1,199 @@
#include <malloc.h>
#include <string.h>
#include "header.h"
#include "read.h"
#include "part.h"
#include "misc.h"
#include "rpmlib.h"
#include "popt/popt.h"
#include "reqprov.h"
#include "package.h"
/* Define this to be 1 to turn on -p "<prog> <args>..." ability */
#define USE_PROG_STRING_ARRAY 0
int parseScript(Spec spec, int parsePart)
{
/* There are a few options to scripts: */
/* <pkg> */
/* -n <pkg> */
/* -p <sh> */
/* -p "<sh> <args>..." */
/* -f <file> */
char *p;
char *name = NULL;
char *prog = "/bin/sh";
char *file = NULL;
char **progArgv = NULL;
int progArgc;
char *partname = NULL;
int tag = 0;
int progtag = 0;
int flag = PART_SUBNAME;
Package pkg;
StringBuf sb;
int nextPart;
int rc, argc;
char arg, **argv = NULL;
poptContext optCon = NULL;
struct poptOption optionsTable[] = {
{ NULL, 'p', POPT_ARG_STRING, &prog, 'p' },
{ NULL, 'n', POPT_ARG_STRING, &name, 'n' },
{ NULL, 'f', POPT_ARG_STRING, &file, 'f' },
{ 0, 0, 0, 0, 0 }
};
switch (parsePart) {
case PART_PRE:
tag = RPMTAG_PREIN;
progtag = RPMTAG_PREINPROG;
partname = "%pre";
break;
case PART_POST:
tag = RPMTAG_POSTIN;
progtag = RPMTAG_POSTINPROG;
partname = "%post";
break;
case PART_PREUN:
tag = RPMTAG_PREUN;
progtag = RPMTAG_PREUNPROG;
partname = "%preun";
break;
case PART_POSTUN:
tag = RPMTAG_POSTUN;
progtag = RPMTAG_POSTUNPROG;
partname = "%postun";
break;
case PART_VERIFYSCRIPT:
tag = PART_VERIFYSCRIPT;
progtag = RPMTAG_VERIFYSCRIPTPROG;
partname = "%verifyscript";
}
if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
rpmError(RPMERR_BADSPEC, "line %d: Error parsing %s: %s",
spec->lineNum, partname, poptStrerror(rc));
return RPMERR_BADSPEC;
}
optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
while ((arg = poptGetNextOpt(optCon)) > 0) {
if (arg == 'p') {
if (prog[0] != '/') {
rpmError(RPMERR_BADSPEC,
"line %d: script program must begin "
"with \'/\': %s", prog);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
} else if (arg == 'n') {
flag = PART_NAME;
}
}
if (arg < -1) {
rpmError(RPMERR_BADSPEC, "line %d: Bad option %s: %s",
spec->lineNum,
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
if (poptPeekArg(optCon)) {
if (! name) {
name = poptGetArg(optCon);
}
if (poptPeekArg(optCon)) {
rpmError(RPMERR_BADSPEC, "line %d: Too many names: %s",
spec->lineNum,
spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
}
if (lookupPackage(spec, name, flag, &pkg)) {
rpmError(RPMERR_BADSPEC, "line %d: Package does not exist: %s",
spec->lineNum, spec->line);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
if (headerIsEntry(pkg->header, progtag)) {
rpmError(RPMERR_BADSPEC, "line %d: Second %s",
spec->lineNum, partname);
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) {
rpmError(RPMERR_BADSPEC, "line %d: Error parsing %s: %s",
spec->lineNum, partname, poptStrerror(rc));
FREE(argv);
poptFreeContext(optCon);
return RPMERR_BADSPEC;
}
sb = newStringBuf();
if (readLine(spec, STRIP_NOTHING) > 0) {
nextPart = PART_NONE;
} else {
while (! (nextPart = isPart(spec->line))) {
appendLineStringBuf(sb, spec->line);
if (readLine(spec, STRIP_NOTHING) > 0) {
nextPart = PART_NONE;
break;
}
}
}
stripTrailingBlanksStringBuf(sb);
p = getStringBuf(sb);
#if USE_PROG_STRING_ARRAY
addReqProv(spec, pkg, RPMSENSE_PREREQ, progArgv[0], NULL);
headerAddEntry(pkg->header, progtag, RPM_STRING_ARRAY_TYPE,
progArgv, progArgc);
#else
addReqProv(spec, pkg, RPMSENSE_PREREQ, prog, NULL);
headerAddEntry(pkg->header, progtag, RPM_STRING_TYPE, prog, 1);
#endif
if (*p) {
headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, p, 1);
}
if (file) {
switch (parsePart) {
case PART_PRE:
pkg->preInFile = strdup(file);
break;
case PART_POST:
pkg->postInFile = strdup(file);
break;
case PART_PREUN:
pkg->preUnFile = strdup(file);
break;
case PART_POSTUN:
pkg->postUnFile = strdup(file);
break;
case PART_VERIFYSCRIPT:
pkg->verifyFile = strdup(file);
break;
}
}
freeStringBuf(sb);
FREE(progArgv);
FREE(argv);
poptFreeContext(optCon);
return nextPart;
}

186
build/parseSpec.c Normal file
View File

@ -0,0 +1,186 @@
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
#include "header.h"
#include "rpmlib.h"
#include "part.h"
#include "spec.h"
#include "parse.h"
#include "read.h"
#include "misc.h"
static void setStandardMacros(Spec spec, char *arch, char *os);
int parseSpec(Spec *specp, char *specFile, char *buildRoot,
int inBuildArch, char *passPhrase, char *cookie)
{
int parsePart = PART_PREAMBLE;
int initialPackage = 1;
char *name, *arch, *os;
Package pkg;
int x, index;
Spec spec;
/* Set up a new Spec structure with no packages. */
spec = newSpec();
spec->specFile = strdup(specFile);
if (buildRoot) {
spec->gotBuildRoot = 1;
spec->buildRoot = strdup(buildRoot);
}
spec->docDir = strdup(rpmGetVar(RPMVAR_DEFAULTDOCDIR));
spec->inBuildArchitectures = inBuildArch;
if (passPhrase) {
spec->passPhrase = strdup(passPhrase);
}
if (cookie) {
spec->cookie = strdup(cookie);
}
if (rpmGetVar(RPMVAR_TIMECHECK)) {
if (parseNum(rpmGetVar(RPMVAR_TIMECHECK), &(spec->timeCheck))) {
rpmError(RPMERR_BADSPEC, "Timecheck value must be an integer: %s",
rpmGetVar(RPMVAR_TIMECHECK));
freeSpec(spec);
return RPMERR_BADSPEC;
}
} else {
spec->timeCheck = 0;
}
/* Add some standard macros */
rpmGetArchInfo(&arch, NULL);
rpmGetOsInfo(&os, NULL);
setStandardMacros(spec, arch, os);
/* All the parse*() functions expect to have a line pre-read */
/* in the spec's line buffer. Except for parsePreamble(), */
/* which handles the initial entry into a spec file. */
while (parsePart != PART_NONE) {
switch (parsePart) {
case PART_PREAMBLE:
parsePart = parsePreamble(spec, initialPackage);
initialPackage = 0;
break;
case PART_PREP:
parsePart = parsePrep(spec);
break;
case PART_BUILD:
case PART_INSTALL:
case PART_CLEAN:
parsePart = parseBuildInstallClean(spec, parsePart);
break;
case PART_CHANGELOG:
parsePart = parseChangelog(spec);
break;
case PART_DESCRIPTION:
parsePart = parseDescription(spec);
break;
case PART_PRE:
case PART_POST:
case PART_PREUN:
case PART_POSTUN:
case PART_VERIFYSCRIPT:
parsePart = parseScript(spec, parsePart);
break;
case PART_FILES:
parsePart = parseFiles(spec);
break;
case PART_TRIGGERIN:
case PART_TRIGGERUN:
printf("Triggers are not supported yet.\n");
exit(1);
/*parsePart = parseTrigger(spec, parsePart);*/
break;
}
if (parsePart < 0) {
freeSpec(spec);
return parsePart;
}
if (parsePart == PART_BUILDARCHITECTURES) {
spec->buildArchitectureSpecs =
malloc(sizeof(Spec) * spec->buildArchitectureCount);
x = 0;
index = 0;
while (x < spec->buildArchitectureCount) {
if (rpmMachineScore(RPM_MACHTABLE_BUILDARCH,
spec->buildArchitectures[x])) {
rpmSetMachine(spec->buildArchitectures[x], NULL);
if (parseSpec(&(spec->buildArchitectureSpecs[index]),
specFile, buildRoot, 1,
passPhrase, cookie)) {
spec->buildArchitectureCount = index;
freeSpec(spec);
return RPMERR_BADSPEC;
}
index++;
}
x++;
}
spec->buildArchitectureCount = index;
if (! index) {
freeSpec(spec);
rpmError(RPMERR_BADSPEC, "No buildable architectures");
return RPMERR_BADSPEC;
}
closeSpec(spec);
*specp = spec;
return 0;
}
}
/* Check for description in each package and add arch and os */
pkg = spec->packages;
while (pkg) {
headerGetEntry(pkg->header, RPMTAG_NAME, NULL, (void **) &name, NULL);
if (!headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) {
rpmError(RPMERR_BADSPEC, "Package has no %%description: %s", name);
freeSpec(spec);
return RPMERR_BADSPEC;
}
headerAddEntry(pkg->header, RPMTAG_OS, RPM_STRING_TYPE, os, 1);
headerAddEntry(pkg->header, RPMTAG_ARCH, RPM_STRING_TYPE, arch, 1);
pkg = pkg->next;
}
closeSpec(spec);
*specp = spec;
return 0;
}
static void setStandardMacros(Spec spec, char *arch, char *os)
{
char buf[BUFSIZ];
int x;
addMacro(&spec->macros, "sourcedir", rpmGetVar(RPMVAR_SOURCEDIR));
addMacro(&spec->macros, "builddir", rpmGetVar(RPMVAR_BUILDDIR));
addMacro(&spec->macros, "optflags", rpmGetVar(RPMVAR_OPTFLAGS));
addMacro(&spec->macros, "buildarch", arch);
addMacro(&spec->macros, "buildos", os);
x = 0;
while (arch[x]) {
buf[x] = tolower(arch[x]);
x++;
}
buf[x] = '\0';
addMacro(&spec->macros, "buildarch_lc", buf);
x = 0;
while (os[x]) {
buf[x] = tolower(os[x]);
x++;
}
buf[x] = '\0';
addMacro(&spec->macros, "buildos_lc", buf);
}

View File

@ -1,22 +1,50 @@
/* handle triggers */
#include "config.h"
#include "miscfn.h"
#include <stdlib.h>
#include <string.h>
#include "trigger.h"
#include "header.h"
#include "spec.h"
#include "specP.h"
#include "messages.h"
#include "rpmlib.h"
#include "stringbuf.h"
#include "misc.h"
/* %trigger is a strange combination of %pre and Requires: behavior */
/* We can handle it by handing the args before "--" to parseScript, */
/* which in the case of triggers should return an index. We then */
/* can pass the remaining arguments to parseReqProv, along with the */
/* index we just obtained. In theory, then, all script arguments */
/* and behavior is in parseScript, and the require behavior is in */
/* parseReqProv, with just a little glue used here. */
#define FREE(x) { if (x) free(x); }
#define CHUNK 8
int parseTrigger(Spec spec, int parsePart)
{
int nextPart;
char **lineArgv, **triggerArgv;
int lineArgc, triggerArgc;
int rc, dash;
if ((rc = poptParseArgvString(spec->line, &lineArgc, &lineArgv))) {
rpmError(RPMERR_BADSPEC, "line %d: Error parsing trigger options: %s",
spec->lineNum, partname, poptStrerror(rc));
return RPMERR_BADSPEC;
}
triggerArgv = lineArgv;
triggerArgc = lineArgc;
dash = 0;
while (dash <= lineArgc) {
if (!strcmp(lineArgv[dash], "--")) {
lineArgv[dash] = NULL;
if ((rc = parseScriptArgs(spec, dash, lineArgv,
&prog, &name, &flag))) {
free(lineArgv);
return rc;
}
triggerArgv = &(lineArgv[dash + 1]);
triggerArgc = lineArgc - dash - 1;
break;
}
dash++;
}
if ((rc = parseReqArgs(spec, triggerArgc, triggerArgv,
}
int addTrigger(struct PackageRec *package,
int sense, char *script, char *args)

56
build/part.c Normal file
View File

@ -0,0 +1,56 @@
#include <string.h>
#include "part.h"
static struct PartRec {
int part;
int len;
char *token;
} partList[] = {
{PART_PREAMBLE, 0, "%package"},
{PART_PREP, 0, "%prep"},
{PART_BUILD, 0, "%build"},
{PART_INSTALL, 0, "%install"},
{PART_CLEAN, 0, "%clean"},
{PART_PREUN, 0, "%preun"},
{PART_POSTUN, 0, "%postun"},
{PART_PRE, 0, "%pre"},
{PART_POST, 0, "%post"},
{PART_FILES, 0, "%files"},
{PART_CHANGELOG, 0, "%changelog"},
{PART_DESCRIPTION, 0, "%description"},
{PART_TRIGGERUN, 0, "%triggerun"},
{PART_TRIGGERIN, 0, "%trigger"},
{PART_VERIFYSCRIPT, 0, "%verifyscript"},
{0, 0, 0}
};
static void initParts(void)
{
struct PartRec *p = partList;
while (p->token) {
p->len = strlen(p->token);
p++;
}
}
int isPart(char *line)
{
struct PartRec *p = partList;
if (p->len == 0) {
initParts();
}
while (p->token && strncmp(line, p->token, p->len)) {
p++;
}
if (p->token) {
return p->part;
} else {
return PART_NONE;
}
}

24
build/part.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _PART_H_
#define _PART_H_
#define PART_NONE 0
#define PART_PREAMBLE 1
#define PART_PREP 2
#define PART_BUILD 3
#define PART_INSTALL 4
#define PART_CLEAN 5
#define PART_FILES 6
#define PART_PRE 7
#define PART_POST 8
#define PART_PREUN 9
#define PART_POSTUN 10
#define PART_DESCRIPTION 11
#define PART_CHANGELOG 12
#define PART_TRIGGERIN 13
#define PART_TRIGGERUN 14
#define PART_VERIFYSCRIPT 15
#define PART_BUILDARCHITECTURES 16
int isPart(char *line);
#endif

138
build/read.c Normal file
View File

@ -0,0 +1,138 @@
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "spec.h"
#include "rpmlib.h"
#include "messages.h"
#include "macro.h"
#include "misc.h"
static int matchTok(char *token, char *line);
/* returns 0 - success */
/* 1 - EOF */
/* <0 - error */
int readLine(Spec spec, int strip)
{
char *from, *to, *last, *s, *arch, *os;
int match;
char ch;
struct ReadLevelEntry *rl;
/* Make sure the spec file is open */
if (!spec->file) {
if (!(spec->file = fopen(spec->specFile, "r"))) {
rpmError(RPMERR_BADSPEC, "Unable to open: %s\n", spec->specFile);
return RPMERR_BADSPEC;
}
spec->lineNum = 0;
}
/* Make sure we have something in the read buffer */
if (!spec->readPtr || ! *(spec->readPtr)) {
if (!fgets(spec->readBuf, BUFSIZ, spec->file)) {
/* EOF */
if (spec->readStack->next) {
rpmError(RPMERR_UNMATCHEDIF, "Unclosed %%if");
return RPMERR_UNMATCHEDIF;
}
return 1;
}
spec->readPtr = spec->readBuf;
spec->lineNum++;
/*rpmMessage(RPMMESS_DEBUG, "LINE: %s", spec->readBuf);*/
}
/* Copy a single line to the line buffer */
from = spec->readPtr;
to = last = spec->line;
ch = ' ';
while (*from && ch != '\n') {
ch = *to++ = *from++;
if (!isspace(ch)) {
last = to;
}
}
*to = '\0';
spec->readPtr = from;
if (strip) {
*last = '\0';
}
rpmGetArchInfo(&arch, NULL);
rpmGetOsInfo(&os, NULL);
s = spec->line;
SKIPSPACE(s);
match = -1;
if (! strncmp("%ifarch", s, 7)) {
match = matchTok(arch, s);
} else if (! strncmp("%ifnarch", s, 8)) {
match = !matchTok(arch, s);
} else if (! strncmp("%ifos", s, 5)) {
match = matchTok(os, s);
} else if (! strncmp("%ifnos", s, 6)) {
match = !matchTok(os, s);
} else if (! strncmp("%else", s, 5)) {
if (! spec->readStack->next) {
/* Got an else with no %if ! */
rpmError(RPMERR_UNMATCHEDIF, "line %d: Got a %%else with no if",
spec->lineNum);
return RPMERR_UNMATCHEDIF;
}
spec->readStack->reading =
spec->readStack->next->reading && ! spec->readStack->reading;
spec->line[0] = '\0';
} else if (! strncmp("%endif", s, 6)) {
if (! spec->readStack->next) {
/* Got an end with no %if ! */
rpmError(RPMERR_UNMATCHEDIF, "line %d: Got a %%endif with no if",
spec->lineNum);
return RPMERR_UNMATCHEDIF;
}
rl = spec->readStack;
spec->readStack = spec->readStack->next;
free(rl);
spec->line[0] = '\0';
}
if (match != -1) {
rl = malloc(sizeof(struct ReadLevelEntry));
rl->reading = spec->readStack->reading && match;
rl->next = spec->readStack;
spec->readStack = rl;
spec->line[0] = '\0';
}
if (spec->readStack->reading) {
expandMacros(&spec->macros, spec->line);
} else {
spec->line[0] = '\0';
}
return 0;
}
static int matchTok(char *token, char *line)
{
char buf[BUFSIZ], *tok;
strcpy(buf, line);
strtok(buf, " \n\t");
while ((tok = strtok(NULL, " \n\t"))) {
if (! strcmp(tok, token)) {
return 1;
}
}
return 0;
}
void closeSpec(Spec spec)
{
if (spec->file) {
fclose(spec->file);
}
spec->file = NULL;
}

16
build/read.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef _READ_H_
#define _READ_H_
#include "spec.h"
#define STRIP_NOTHING 0
#define STRIP_TRAILINGSPACE 1
/* returns 0 - success */
/* 1 - EOF */
/* <0 - error */
int readLine(Spec spec, int strip);
void closeSpec(Spec spec);
#endif

View File

@ -1,413 +1,211 @@
/* reqprov.c -- require/provide handling */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <malloc.h>
#include "specP.h"
#include "spec.h"
#include "reqprov.h"
#include "messages.h"
#include "rpmlib.h"
#include "misc.h"
#include "lib/misc.h"
static StringBuf getOutputFrom(char *dir, char *argv[],
char *writePtr, int writeBytesLeft,
int failNonZero);
/*************************************************************/
/* */
/* Adding entries to the package reqprov list */
/* Handle duplicate entries */
/* */
/*************************************************************/
int addReqProv(struct PackageRec *p, int flags,
char *name, char *version)
int addReqProv(Spec spec, Package pkg, int flag, char *name, char *version)
{
struct ReqProv *rd;
int same;
/* Frist see if the same entry is already there */
rd = p->reqprov;
while (rd) {
if (rd->flags == flags) {
if (rd->version == version) {
same = 1;
} else if (!rd->version || !version) {
same = 0;
} else if (!strcmp(rd->version, version)) {
same = 1;
} else {
same = 0;
}
if (same && !strcmp(rd->name, name)) {
/* They are exacty the same */
break;
}
}
rd = rd->next;
char **names;
char **versions = NULL;
int *flags = NULL;
int nametag = 0;
int versiontag = 0;
int flagtag = 0;
int len;
int extra = 0;
if (flag & RPMSENSE_PROVIDES) {
nametag = RPMTAG_PROVIDES;
} else if (flag & RPMSENSE_OBSOLETES) {
nametag = RPMTAG_OBSOLETES;
} else if (flag & RPMSENSE_CONFLICTS) {
nametag = RPMTAG_CONFLICTNAME;
versiontag = RPMTAG_CONFLICTVERSION;
flagtag = RPMTAG_CONFLICTFLAGS;
} else if (flag & RPMSENSE_PREREQ) {
nametag = RPMTAG_REQUIRENAME;
versiontag = RPMTAG_REQUIREVERSION;
flagtag = RPMTAG_REQUIREFLAGS;
extra = RPMSENSE_PREREQ;
} else {
nametag = RPMTAG_REQUIRENAME;
versiontag = RPMTAG_REQUIREVERSION;
flagtag = RPMTAG_REQUIREFLAGS;
}
if (rd) {
/* already there */
rpmMessage(RPMMESS_DEBUG, "Already Got: %s\n", name);
return 0;
flag = (flag & RPMSENSE_SENSEMASK) | extra;
if (!version) {
version = "";
}
rd = (struct ReqProv *)malloc(sizeof(*rd));
rd->flags = flags;
rd->name = strdup(name);
rd->version = version ? strdup(version) : NULL;
rd->next = p->reqprov;
p->reqprov = rd;
if (headerGetEntry(pkg->header, nametag, NULL, (void *) &names, &len)) {
if (flagtag) {
headerGetEntry(pkg->header, versiontag, NULL,
(void *) &versions, NULL);
headerGetEntry(pkg->header, flagtag, NULL, (void *) &flags, NULL);
}
while (len) {
len--;
if (!strcmp(names[len], name)) {
if (!flagtag ||
(!strcmp(versions[len], version) && flags[len] == flag)) {
/* The same */
FREE(names);
FREE(versions);
return 0;
}
}
}
FREE(names);
FREE(versions);
}
if (flags & RPMSENSE_PROVIDES) {
rpmMessage(RPMMESS_DEBUG, "Adding provide: %s\n", name);
p->numProv++;
} else if (flags & RPMSENSE_CONFLICTS) {
rpmMessage(RPMMESS_DEBUG, "Adding conflict: %s\n", name);
p->numConflict++;
} else if (flags & RPMSENSE_PREREQ) {
rpmMessage(RPMMESS_DEBUG, "Adding prereq: %s\n", name);
p->numPreReq++;
} else if (flags & RPMSENSE_OBSOLETES) {
rpmMessage(RPMMESS_DEBUG, "Adding obsoletes: %s\n", name);
p->numObsoletes++;
} else {
rpmMessage(RPMMESS_DEBUG, "Adding require: %s\n", name);
p->numReq++;
headerAddOrAppendEntry(pkg->header, nametag,
RPM_STRING_ARRAY_TYPE, &name, 1);
if (flagtag) {
headerAddOrAppendEntry(pkg->header, versiontag,
RPM_STRING_ARRAY_TYPE, &version, 1);
headerAddOrAppendEntry(pkg->header, flagtag,
RPM_INT32_TYPE, &flag, 1);
}
return 0;
}
/*************************************************************/
/* */
/* Add require/provides for the files in the header */
/* (adds to the package structure) */
/* */
/*************************************************************/
static StringBuf getOutputFrom(char *dir, char *argv[],
char *writePtr, int writeBytesLeft,
int failNonZero)
int generateAutoReqProv(Spec spec, Package pkg,
struct cpioFileMapping *cpioList, int cpioCount)
{
int progPID;
int progDead;
int toProg[2];
int fromProg[2];
int status;
void *oldhandler;
int bytesWritten;
StringBuf readBuff;
int bytes;
unsigned char buf[8193];
oldhandler = signal(SIGPIPE, SIG_IGN);
pipe(toProg);
pipe(fromProg);
if (!(progPID = fork())) {
close(toProg[1]);
close(fromProg[0]);
dup2(toProg[0], 0); /* Make stdin the in pipe */
dup2(fromProg[1], 1); /* Make stdout the out pipe */
close(toProg[0]);
close(fromProg[1]);
chdir(dir);
execvp(argv[0], argv);
rpmError(RPMERR_EXEC, "Couldn't exec %s", argv[0]);
_exit(RPMERR_EXEC);
}
if (progPID < 0) {
rpmError(RPMERR_FORK, "Couldn't fork %s", argv[0]);
return NULL;
}
close(toProg[0]);
close(fromProg[1]);
/* Do not block reading or writing from/to prog. */
fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
fcntl(toProg[1], F_SETFL, O_NONBLOCK);
readBuff = newStringBuf();
progDead = 0;
do {
if (waitpid(progPID, &status, WNOHANG)) {
progDead = 1;
}
/* Write some stuff to the process if possible */
if (writeBytesLeft) {
if ((bytesWritten =
write(toProg[1], writePtr,
(1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
if (errno != EAGAIN) {
perror("getOutputFrom()");
exit(1);
}
bytesWritten = 0;
}
writeBytesLeft -= bytesWritten;
writePtr += bytesWritten;
} else {
close(toProg[1]);
}
/* Read any data from prog */
bytes = read(fromProg[0], buf, sizeof(buf)-1);
while (bytes > 0) {
buf[bytes] = '\0';
appendStringBuf(readBuff, buf);
bytes = read(fromProg[0], buf, sizeof(buf)-1);
}
/* terminate when prog dies */
} while (!progDead);
close(toProg[1]);
close(fromProg[0]);
signal(SIGPIPE, oldhandler);
if (writeBytesLeft) {
rpmError(RPMERR_EXEC, "failed to write all data to %s", argv[0]);
return NULL;
}
waitpid(progPID, &status, 0);
if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
rpmError(RPMERR_EXEC, "%s failed", argv[0]);
return NULL;
}
return readBuff;
}
int generateAutoReqProv(Header header, struct PackageRec *p)
{
char **f, **fsave, *s;
int count;
int_16 *modes;
StringBuf writeBuff;
StringBuf readBuff;
char *writePtr;
StringBuf writeBuf;
int writeBytes;
char dir[1024];
char *argv[8];
StringBuf readBuf;
char *argv[2];
char **f, **fsave;
rpmMessage(RPMMESS_VERBOSE, "Finding dependencies...\n");
/*** Get root directory ***/
if (rpmGetVar(RPMVAR_ROOT)) {
strcpy(dir, rpmGetVar(RPMVAR_ROOT));
} else {
strcpy(dir, "/");
}
/*** Generate File List ***/
if (!headerGetEntry(header, RPMTAG_FILENAMES, NULL, (void **) &f, &count)) {
if (!cpioCount) {
return 0;
}
if (!count) {
return 0;
}
fsave = f;
headerGetEntry(header, RPMTAG_FILEMODES, NULL, (void **) &modes, NULL);
writeBuff = newStringBuf();
writeBuf = newStringBuf();
writeBytes = 0;
while (count--) {
s = *f++;
/* We skip the leading "/" (already normalized) */
writeBytes += strlen(s);
appendLineStringBuf(writeBuff, s + 1);
while (cpioCount--) {
writeBytes += strlen(cpioList->fsPath) + 1;
appendLineStringBuf(writeBuf, cpioList->fsPath);
cpioList++;
}
if (fsave) {
free(fsave);
}
writePtr = getStringBuf(writeBuff);
/*** Do Provides ***/
rpmMessage(RPMMESS_NORMAL, "Finding provides...\n");
argv[0] = "find-provides";
argv[1] = NULL;
readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 1);
if (!readBuff) {
readBuf = getOutputFrom(NULL, argv,
getStringBuf(writeBuf), writeBytes, 1);
if (!readBuf) {
rpmError(RPMERR_EXEC, "Failed to find provides");
exit(1);
freeStringBuf(writeBuf);
return RPMERR_EXEC;
}
s = getStringBuf(readBuff);
f = fsave = splitString(s, strlen(s), '\n');
freeStringBuf(readBuff);
f = fsave = splitString(getStringBuf(readBuf),
strlen(getStringBuf(readBuf)), '\n');
freeStringBuf(readBuf);
while (*f) {
if (**f) {
addReqProv(p, RPMSENSE_PROVIDES, *f, NULL);
addReqProv(spec, pkg, RPMSENSE_PROVIDES, *f, NULL);
}
f++;
}
free(fsave);
FREE(fsave);
/*** Do Requires ***/
rpmMessage(RPMMESS_NORMAL, "Finding requires...\n");
argv[0] = "find-requires";
argv[1] = NULL;
readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 0);
if (!readBuff) {
readBuf = getOutputFrom(NULL, argv,
getStringBuf(writeBuf), writeBytes, 0);
if (!readBuf) {
rpmError(RPMERR_EXEC, "Failed to find requires");
exit(1);
freeStringBuf(writeBuf);
return RPMERR_EXEC;
}
s = getStringBuf(readBuff);
f = fsave = splitString(s, strlen(s), '\n');
freeStringBuf(readBuff);
f = fsave = splitString(getStringBuf(readBuf),
strlen(getStringBuf(readBuf)), '\n');
freeStringBuf(readBuf);
while (*f) {
if (**f) {
addReqProv(p, RPMSENSE_ANY, *f, NULL);
addReqProv(spec, pkg, RPMSENSE_ANY, *f, NULL);
}
f++;
}
free(fsave);
FREE(fsave);
/*** Clean Up ***/
freeStringBuf(writeBuff);
freeStringBuf(writeBuf);
return 0;
}
/*************************************************************/
/* */
/* Generate and add header entry from package record */
/* */
/*************************************************************/
int processReqProv(Header h, struct PackageRec *p)
void printReqs(Spec spec, Package pkg)
{
struct ReqProv *rd;
char **nameArray, **namePtr;
char **versionArray, **versionPtr;
int_32 *flagArray, *flagPtr;
int x;
int startedPreReq = 0;
int startedReq = 0;
if (p->numProv) {
rd = p->reqprov;
nameArray = namePtr = malloc(p->numProv * sizeof(*nameArray));
rpmMessage(RPMMESS_VERBOSE, "Provides (%d):", p->numProv);
while (rd) {
if (rd->flags & RPMSENSE_PROVIDES) {
rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
*namePtr++ = rd->name;
}
rd = rd->next;
char **names;
int x, count;
int *flags;
if (headerGetEntry(pkg->header, RPMTAG_PROVIDES,
NULL, (void **) &names, &count)) {
rpmMessage(RPMMESS_NORMAL, "Provides:");
x = 0;
while (x < count) {
rpmMessage(RPMMESS_NORMAL, " %s", names[x]);
x++;
}
rpmMessage(RPMMESS_VERBOSE, "\n");
headerAddEntry(h, RPMTAG_PROVIDES, RPM_STRING_ARRAY_TYPE, nameArray, p->numProv);
free(nameArray);
rpmMessage(RPMMESS_NORMAL, "\n");
FREE(names);
}
if (p->numObsoletes) {
rd = p->reqprov;
nameArray = namePtr = malloc(p->numObsoletes * sizeof(*nameArray));
rpmMessage(RPMMESS_VERBOSE, "Obsoletes (%d):", p->numObsoletes);
while (rd) {
if (rd->flags & RPMSENSE_OBSOLETES) {
rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
*namePtr++ = rd->name;
}
rd = rd->next;
}
rpmMessage(RPMMESS_VERBOSE, "\n");
headerAddEntry(h, RPMTAG_OBSOLETES, RPM_STRING_ARRAY_TYPE, nameArray, p->numObsoletes);
free(nameArray);
}
if (p->numConflict) {
rd = p->reqprov;
nameArray = namePtr = malloc(p->numConflict * sizeof(*nameArray));
versionArray = versionPtr =
malloc(p->numConflict * sizeof(*versionArray));
flagArray = flagPtr = malloc(p->numConflict * sizeof(*flagArray));
rpmMessage(RPMMESS_VERBOSE, "Conflicts (%d):", p->numConflict);
while (rd) {
if (rd->flags & RPMSENSE_CONFLICTS) {
rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
*namePtr++ = rd->name;
*versionPtr++ = rd->version ? rd->version : "";
*flagPtr++ = rd->flags & RPMSENSE_SENSEMASK;
}
rd = rd->next;
}
rpmMessage(RPMMESS_VERBOSE, "\n");
headerAddEntry(h, RPMTAG_CONFLICTNAME, RPM_STRING_ARRAY_TYPE,
nameArray, p->numConflict);
headerAddEntry(h, RPMTAG_CONFLICTVERSION, RPM_STRING_ARRAY_TYPE,
versionArray, p->numConflict);
headerAddEntry(h, RPMTAG_CONFLICTFLAGS, RPM_INT32_TYPE,
flagArray, p->numConflict);
free(nameArray);
free(versionArray);
free(flagArray);
}
x = p->numReq + p->numPreReq;
if (x) {
rd = p->reqprov;
nameArray = namePtr = malloc(x * sizeof(*nameArray));
versionArray = versionPtr = malloc(x * sizeof(*versionArray));
flagArray = flagPtr = malloc(x * sizeof(*flagArray));
rpmMessage(RPMMESS_VERBOSE, "[Pre]Requires (%d):", x);
while (rd) {
if (! ((rd->flags & RPMSENSE_PROVIDES) ||
(rd->flags & RPMSENSE_OBSOLETES) ||
(rd->flags & RPMSENSE_CONFLICTS))) {
if (rd->flags & RPMSENSE_PREREQ) {
rpmMessage(RPMMESS_VERBOSE, " [%s]", rd->name);
} else {
rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
if (headerGetEntry(pkg->header, RPMTAG_REQUIRENAME,
NULL, (void **) &names, &count)) {
headerGetEntry(pkg->header, RPMTAG_REQUIREFLAGS,
NULL, (void **) &flags, NULL);
x = 0;
while (x < count) {
if (flags[x] & RPMSENSE_PREREQ) {
if (! startedPreReq) {
rpmMessage(RPMMESS_NORMAL, "Prereqs:");
startedPreReq = 1;
}
*namePtr++ = rd->name;
*versionPtr++ = rd->version ? rd->version : "";
*flagPtr++ = (rd->flags & RPMSENSE_SENSEMASK) |
(rd->flags & RPMSENSE_PREREQ);
rpmMessage(RPMMESS_NORMAL, " %s", names[x]);
}
rd = rd->next;
x++;
}
rpmMessage(RPMMESS_VERBOSE, "\n");
headerAddEntry(h, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE,
nameArray, x);
headerAddEntry(h, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE,
versionArray, x);
headerAddEntry(h, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE,
flagArray, x);
free(nameArray);
free(versionArray);
free(flagArray);
rpmMessage(RPMMESS_NORMAL, "\n");
x = 0;
while (x < count) {
if (! (flags[x] & RPMSENSE_PREREQ)) {
if (! startedReq) {
rpmMessage(RPMMESS_NORMAL, "Requires:");
startedReq = 1;
}
rpmMessage(RPMMESS_NORMAL, " %s", names[x]);
}
x++;
}
rpmMessage(RPMMESS_NORMAL, "\n");
FREE(names);
}
return 0;
}

View File

@ -1,11 +1,13 @@
#ifndef _REQPROV_H_
#define _REQPROV_H_
#include "specP.h"
#include "spec.h"
#include "package.h"
#include "lib/cpio.h"
int addReqProv(struct PackageRec *p, int flags,
char *name, char *version);
int generateAutoReqProv(Header header, struct PackageRec *p);
int processReqProv(Header h, struct PackageRec *p);
int addReqProv(Spec spec, Package pkg, int flag, char *name, char *version);
int generateAutoReqProv(Spec spec, Package pkg,
struct cpioFileMapping *cpioList, int cpioCount);
void printReqs(Spec spec, Package pkg);
#endif _REQPROV_H_
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +1,127 @@
/* RPM - Copyright (C) 1995 Red Hat Software
*
* spec.h - routines for parsing are looking up info in a spec file
*/
#ifndef _SPEC_H_
#define _SPEC_H_
#include <stdio.h>
#include "header.h"
#include "stringbuf.h"
#include "macro.h"
typedef struct SpecRec *Spec;
#if 0
struct ReqProvTrigger {
int flags;
char *name;
char *version;
int index; /* Only used for triggers */
struct ReqProvTrigger *next;
};
#endif
Spec *parseSpec(FILE *f, char *specfile, char *buildRootOverride);
void freeSpec(Spec s);
#define RPMBUILD_ISSOURCE 1
#define RPMBUILD_ISPATCH (1 << 1)
#define RPMBUILD_ISICON (1 << 2)
#define RPMBUILD_ISNO (1 << 3)
void dumpSpec(Spec s, FILE *f);
#define RPMBUILD_DEFAULT_LANG "C"
char *getSource(Spec s, int ispatch, int num);
char *getFullSource(Spec s, int ispatch, int num);
struct Source {
char *fullSource;
char *source; /* Pointer into fullSource */
int flags;
int num;
struct Source *next;
};
int verifySpec(Spec s);
struct ReadLevelEntry {
int reading;
struct ReadLevelEntry *next;
};
struct SpecStruct {
char *specFile;
char *sourceRpmName;
FILE *file;
char readBuf[BUFSIZ];
char *readPtr;
char line[BUFSIZ];
int lineNum;
struct ReadLevelEntry *readStack;
Header buildRestrictions;
struct SpecStruct **buildArchitectureSpecs;
char ** buildArchitectures;
int buildArchitectureCount;
int inBuildArchitectures;
int gotBuildRoot;
char *buildRoot;
char *buildSubdir;
char *docDir;
char *passPhrase;
int timeCheck;
char *cookie;
struct Source *sources;
int numSources;
int noSource;
Header sourceHeader;
int sourceCpioCount;
struct cpioFileMapping *sourceCpioList;
struct MacroContext macros;
int autoReqProv;
StringBuf prep;
StringBuf build;
StringBuf install;
StringBuf clean;
struct PackageStruct *packages;
};
struct PackageStruct {
Header header;
int cpioCount;
struct cpioFileMapping *cpioList;
struct Source *icon;
int autoReqProv;
char *preInFile;
char *postInFile;
char *preUnFile;
char *postUnFile;
char *verifyFile;
StringBuf specialDoc;
#if 0
struct ReqProvTrigger *triggers;
char *triggerScripts;
#endif
char *fileFile;
StringBuf fileList; /* If NULL, package will not be written */
struct PackageStruct *next;
};
typedef struct SpecStruct *Spec;
typedef struct PackageStruct *Package;
Spec newSpec(void);
void freeSpec(Spec spec);
int addSource(Spec spec, Package pkg, char *field, int tag);
char *getSource(Spec spec, int num, int flag);
char *getFullSource(Spec spec, int num, int flag);
void freeSources(Spec spec);
int parseNoSource(Spec spec, char *field, int tag);
#endif _SPEC_H_

View File

@ -1,97 +0,0 @@
#ifndef _SPECP_H_
#define _SPECP_H_
#include "spec.h"
#include "header.h"
#include "stringbuf.h"
typedef struct sources {
char *fullSource;
char *source;
int ispatch;
int num;
struct sources *next;
} *Sources;
struct ReqProv {
int flags;
char *name;
char *version;
struct ReqProv *next;
};
struct TriggerEntry {
int flags;
char *name;
char *version;
int index;
struct TriggerEntry *next;
};
struct TriggerStruct {
char **triggerScripts;
int alloced;
int used;
int triggerCount;
struct TriggerEntry *trigger;
};
struct SpecRec {
char *name; /* package base name */
char *specfile;
int numSources;
int numPatches;
Sources sources;
int numNoSource;
int numNoPatch;
int_32 *noSource;
int_32 *noPatch;
int autoReqProv;
StringBuf prep;
StringBuf build;
StringBuf install;
StringBuf doc;
StringBuf clean;
char *buildroot;
char *buildArch;
struct PackageRec *packages;
/* The first package record is the "main" package and contains
* the bulk of the preamble information. Subsequent package
* records "inherit" from the main record. Note that the
* "main" package may be, in pre-rpm-2.0 terms, a "subpackage".
*/
};
struct PackageRec {
char *subname; /* If both of these are NULL, then this is */
char *newname; /* the main package. subname concats with name */
Header header;
char *icon;
int files; /* If -1, package has no files, and won't be written */
char *fileFile;
StringBuf filelist;
StringBuf doc; /* Used to buffer up %doc lines until fully parsed */
int numReq;
int numPreReq;
int numProv;
int numConflict;
int numObsoletes;
struct ReqProv *reqprov;
struct PackageRec *next;
struct TriggerStruct trigger;
};
struct ReqComp {
char *token;
int flags;
};
extern struct ReqComp ReqComparisons[];
#endif _SPECP_H_

View File

@ -1,13 +0,0 @@
#ifndef _TRIGGER_H_
#define _TRIGGER_H_
#include "specP.h"
int addTrigger(struct PackageRec *package,
int sense, char *script, char *args);
void generateTriggerEntries(Header h, struct PackageRec *p);
void freeTriggers(struct TriggerStruct t);
#endif _TRIGGER_H_

View File

@ -1,206 +0,0 @@
/* 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;
/* 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;
}

View File

@ -34,6 +34,12 @@ all: $(TARGET)
allprogs: $(LIBRPM) $(PROGS)
misc.o:
$(CC) $(CFLAGS) -DVERSION=\"$(VERSION)\" -o $@ -c $<
rpmrc.o:
$(CC) $(CFLAGS) -DLIBRPMRC_FILENAME="\"$(LIBRPMRC_FILENAME)"\" -o $@ -c $<
$(PROGS): $(LIBRPM)
$(LIBRPM): $(LIBRPM)($(LIBOBJECTS) $(TAGTABLE))

View File

@ -23,7 +23,7 @@
#include "rpmlib.h"
#include "messages.h"
char * RPMVERSION = VERSION;
char * RPMVERSION = VERSION; /* just to put a marker in librpm.a */
char ** splitString(char * str, int length, char sep) {
char * s, * source, * dest;

201
rpm.c
View File

@ -17,6 +17,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include "build.h"
#include "build/build.h"
#include "checksig.h"
#include "install.h"
@ -42,6 +43,7 @@
#define GETOPT_TIMECHECK 1012
#define GETOPT_REBUILDDB 1013
#define GETOPT_INSTALL 1014
#define GETOPT_RMSOURCE 1015
char * version = VERSION;
@ -62,8 +64,6 @@ static void printVersion(void);
static void printBanner(void);
static void printUsage(void);
static void printHelpLine(char * prefix, char * help);
static int build(char *arg, int buildAmount, char *passPhrase,
char *buildRootOverride, int fromTarball);
static void printVersion(void) {
printf(_("RPM version %s\n"), version);
@ -113,7 +113,8 @@ static void printUsage(void) {
puts(_(" [--justdb] package1 ... packageN"));
puts(_(" rpm {-b|t}[plciba] [-v] [--short-circuit] [--clean] [--rcfile <file>]"));
puts(_(" [--sign] [--test] [--timecheck <s>] [--buildos <os>]"));
puts(_(" [--buildarch <arch>] specfile"));
puts(_(" [--buildarch <arch>] [--rmsource] specfile"));
puts(_(" rpm {--rmsource} [--rcfile <file>] [-v] specfile"));
puts(_(" rpm {--rebuild} [--rcfile <file>] [-v] source1.rpm ... sourceN.rpm"));
puts(_(" rpm {--recompile} [--rcfile <file>] [-v] source1.rpm ... sourceN.rpm"));
puts(_(" rpm {--resign} [--rcfile <file>] package1 package2 ... packageN"));
@ -325,6 +326,8 @@ static void printHelp(void) {
_("skip straight to specified stage (only for c,i)"));
printHelpLine(" --clean ",
_("remove build tree when done"));
printHelpLine(" --rmsource ",
_("remove sources and spec file when done"));
printHelpLine(" --sign ",
_("generate PGP signature"));
printHelpLine(" --buildroot <dir> ",
@ -340,6 +343,8 @@ static void printHelp(void) {
puts("");
printHelpLine(" --rebuild <src_pkg> ",
_("install source package, build binary package and remove spec file, sources, patches, and icons."));
printHelpLine(" --rmsource <spec> ",
_("remove sources and spec file"));
printHelpLine(" --recompile <src_pkg> ",
_("like --rebuild, but don't build any package"));
printHelpLine(" --resign <pkg>+ ",
@ -365,144 +370,6 @@ static void printHelp(void) {
_("use <dir> as the top level directory"));
}
static int build(char *arg, int buildAmount, char *passPhrase,
char *buildRootOverride, int fromTarball) {
FILE *f;
Spec *s, *specArray;
char * specfile;
int res = 0;
struct stat statbuf;
char * specDir;
char * tmpSpecFile;
char * cmd;
char buf[1024];
int flags;
if (fromTarball) {
specDir = rpmGetVar(RPMVAR_SPECDIR);
tmpSpecFile = alloca(1024);
sprintf(tmpSpecFile, "%s/rpm-spec-file-%d", specDir, (int) getpid());
cmd = alloca(strlen(arg) + 50 + strlen(tmpSpecFile));
sprintf(cmd, "gunzip < %s | tar xOvf - \\*.spec 2>&1 > %s", arg,
tmpSpecFile);
if (!(f = popen(cmd, "r"))) {
fprintf(stderr, _("Failed to open tar pipe: %s\n"),
strerror(errno));
return 1;
}
if (!fgets(buf, sizeof(buf) - 1, f)) {
fprintf(stderr, _("Failed to read spec file from %s\n"), arg);
unlink(tmpSpecFile);
return 1;
}
pclose(f);
cmd = specfile = buf;
while (*cmd) {
if (*cmd == '/') specfile = cmd + 1;
cmd++;
}
cmd = specfile;
/* remove trailing \n */
specfile = cmd + strlen(cmd) - 1;
*specfile = '\0';
specfile = alloca(strlen(specDir) + strlen(cmd) + 5);
sprintf(specfile, "%s/%s", specDir, cmd);
if (rename(tmpSpecFile, specfile)) {
fprintf(stderr, _("Failed to rename %s to %s: %s\n"),
tmpSpecFile, specfile, strerror(errno));
unlink(tmpSpecFile);
return 1;
}
/* Make the directory which contains the tarball the source
directory for this run */
if (*arg != '/') {
/* XXX this is broken if PWD is near 1024 */
getcwd(buf, 1024);
strcat(buf, "/");
strcat(buf, arg);
} else
strcpy(buf, arg);
cmd = buf + strlen(buf) - 1;
while (*cmd != '/') cmd--;
*cmd = '\0';
rpmSetVar(RPMVAR_SOURCEDIR, buf);
} else if (arg[0] == '/') {
specfile = arg;
} else {
/* XXX this is broken if PWD is near 1024 */
specfile = alloca(1024);
getcwd(specfile, 1024);
strcat(specfile, "/");
strcat(specfile, arg);
}
stat(specfile, &statbuf);
if (! S_ISREG(statbuf.st_mode)) {
rpmError(RPMERR_BADSPEC, _("File is not a regular file: %s\n"),
specfile);
return 1;
}
if (!(f = fopen(specfile, "r"))) {
fprintf(stderr, _("unable to open: %s\n"), specfile);
return 1;
}
s = specArray = parseSpec(f, specfile, buildRootOverride);
fclose(f);
if (! specArray) {
/* Spec parse failed -- could be Exclude: Exclusive: */
res = 1;
if (rpmErrorCode() == RPMERR_BADARCH) {
fprintf(stderr, _("%s doesn't build on this architecture\n"), arg);
} else {
fprintf(stderr, _("Build failed.\n"));
}
} else {
while (*s && !res) {
if (verifySpec(*s)) {
fprintf(stderr, _("\n%cSpec file check failed!!\n"), 7);
fprintf(stderr,
_("Tell rpm-list@redhat.com if this is incorrect.\n\n"));
res = 1;
} else {
flags = buildAmount;
/* Don't build source package or remove sources */
/* unless this is the last package being built. */
if (*(s+1)) {
flags = flags & ~RPMBUILD_SOURCE;
flags = flags & ~RPMBUILD_RMSOURCE;
}
if (doBuild(*s, flags, passPhrase)) {
fprintf(stderr, _("Build failed.\n"));
res = 1;
}
}
s++;
}
s = specArray;
while (*s) {
freeSpec(*s++);
}
free(specArray);
}
if (fromTarball) unlink(specfile);
return res;
}
int main(int argc, char ** argv) {
enum modes bigMode = MODE_UNKNOWN;
enum querysources querySource = QUERY_PACKAGE;
@ -516,9 +383,8 @@ int main(int argc, char ** argv) {
int incldocs = 0, noScripts = 0, noDeps = 0, allMatches = 0, noOrder = 0;
int noPgp = 0, dump = 0, initdb = 0, ignoreArch = 0, showrc = 0;
int gotDbpath = 0, building = 0, ignoreOs = 0, noFiles = 0, verifyFlags;
int noMd5 = 0, allFiles = 0, justdb = 0;
int noMd5 = 0, allFiles = 0, justdb = 0, rmsource = 0;
int checksigFlags = 0;
char *tce;
int timeCheck = 0;
int addSign = NEW_SIGNATURE;
char * rcfile = NULL, * queryFormat = NULL, * prefix = NULL;
@ -526,11 +392,12 @@ int main(int argc, char ** argv) {
char * rootdir = "/";
char * pipeOutput = NULL;
char * specFile;
char *passPhrase = "";
char *buildRootOverride = NULL;
char *arch = NULL;
char * tce;
char * passPhrase = "";
char * buildRootOverride = NULL, * cookie = NULL;
char * arch = NULL;
char * ftpProxy = NULL, * ftpPort = NULL;
char *os = NULL;
char * os = NULL;
char * optArg;
pid_t pipeChild = 0;
char * pkg;
@ -599,6 +466,7 @@ int main(int argc, char ** argv) {
{ "replacefiles", '\0', 0, &replaceFiles, 0 },
{ "replacepkgs", '\0', 0, &replacePackages, 0 },
{ "resign", '\0', 0, 0, GETOPT_RESIGN },
{ "rmsource", '\0', 0, 0, GETOPT_RMSOURCE },
{ "root", 'r', POPT_ARG_STRING, &rootdir, 0 },
{ "short-circuit", '\0', 0, &shortCircuit, 0 },
{ "showrc", '\0', 0, 0, 0 },
@ -643,6 +511,7 @@ int main(int argc, char ** argv) {
!strcmp(*currarg, "--tarbuild") ||
!strcmp(*currarg, "--build") ||
!strcmp(*currarg, "--rebuild") ||
!strcmp(*currarg, "--rmsource") ||
!strcmp(*currarg, "--recompile")) {
building = 1;
}
@ -839,10 +708,17 @@ int main(int argc, char ** argv) {
bigMode = MODE_REBUILD;
break;
case GETOPT_RMSOURCE:
if (bigMode != MODE_UNKNOWN && bigMode != MODE_BUILD)
argerror(_("only one major mode may be specified"));
bigMode = MODE_BUILD;
break;
case GETOPT_RECOMPILE:
if (bigMode != MODE_UNKNOWN && bigMode != MODE_RECOMPILE)
argerror(_("only one major mode may be specified"));
bigMode = MODE_RECOMPILE;
rmsource = 1;
break;
case GETOPT_BUILDROOT:
@ -890,6 +766,7 @@ int main(int argc, char ** argv) {
argerror("Argument to --timecheck must be integer");
}
rpmSetVar(RPMVAR_TIMECHECK, optArg);
timeCheck = 1;
break;
case GETOPT_REBUILDDB:
@ -1042,6 +919,9 @@ int main(int argc, char ** argv) {
if (bigMode != MODE_BUILD && bigMode != MODE_TARBUILD && clean)
argerror(_("--clean may only be used during package building"));
if (bigMode != MODE_BUILD && bigMode != MODE_TARBUILD && rmsource)
argerror(_("--rmsource may only be used during package building"));
if (bigMode != MODE_BUILD && bigMode != MODE_TARBUILD && shortCircuit)
argerror(_("--short-circuit may only be used during package building"));
@ -1164,19 +1044,21 @@ int main(int argc, char ** argv) {
argerror(_("no packages files given for rebuild"));
buildAmount = RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL |
RPMBUILD_SWEEP | RPMBUILD_RMSOURCE;
RPMBUILD_CLEAN | RPMBUILD_RMSOURCE;
if (bigMode == MODE_REBUILD) {
buildAmount |= RPMBUILD_BINARY;
buildAmount |= RPMBUILD_PACKAGEBINARY;
}
while ((pkg = poptGetArg(optCon))) {
if (doSourceInstall("/", pkg, &specFile, NULL))
if (doSourceInstall("/", pkg, &specFile, &cookie))
exit(1);
if (build(specFile, buildAmount, passPhrase, buildRootOverride,
0)) {
0, test, cookie)) {
exit(1);
}
free(cookie);
free(specFile);
}
break;
@ -1188,9 +1070,10 @@ int main(int argc, char ** argv) {
switch (buildChar) {
/* these fallthroughs are intentional */
case 'a':
buildAmount |= RPMBUILD_SOURCE;
buildAmount |= RPMBUILD_PACKAGESOURCE;
case 'b':
buildAmount |= RPMBUILD_BINARY;
buildAmount |= RPMBUILD_PACKAGEBINARY;
buildAmount |= RPMBUILD_CLEAN;
case 'i':
buildAmount |= RPMBUILD_INSTALL;
if ((buildChar == 'i') && shortCircuit)
@ -1204,15 +1087,15 @@ int main(int argc, char ** argv) {
break;
case 'l':
buildAmount |= RPMBUILD_LIST;
buildAmount |= RPMBUILD_FILECHECK;
break;
}
if (clean)
buildAmount |= RPMBUILD_SWEEP;
if (rmsource)
buildAmount |= RPMBUILD_RMSOURCE;
if (test)
buildAmount |= RPMBUILD_TEST;
if (clean)
buildAmount |= RPMBUILD_RMBUILD;
if (!poptPeekArg(optCon))
if (bigMode == MODE_BUILD)
@ -1222,7 +1105,7 @@ int main(int argc, char ** argv) {
while ((pkg = poptGetArg(optCon)))
if (build(pkg, buildAmount, passPhrase, buildRootOverride,
bigMode == MODE_TARBUILD)) {
bigMode == MODE_TARBUILD, test, NULL)) {
exit(1);
}
break;

View File

@ -1,6 +1,6 @@
Summary: Red Hat Package Manager
Name: rpm
%define version 2.4.12
%define version 2.4.99
Version: %{version}
Release: 1
Group: Utilities/System