summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorewt <devnull@localhost>1998-01-12 21:31:29 +0000
committerewt <devnull@localhost>1998-01-12 21:31:29 +0000
commit757e50ffc827297e36f793cf79ddc471878f6d0b (patch)
treedc29d9ef04a9462998bdfaaa3ee7054585fe01c8
parentec07f9df959c911c60727ba68c455f4ff20497bf (diff)
downloadrpm-757e50ffc827297e36f793cf79ddc471878f6d0b.tar.gz
rpm-757e50ffc827297e36f793cf79ddc471878f6d0b.tar.bz2
rpm-757e50ffc827297e36f793cf79ddc471878f6d0b.zip
merged in Marc's new build code
CVS patchset: 1956 CVS date: 1998/01/12 21:31:29
-rw-r--r--CHANGES31
-rw-r--r--Makefile.in13
-rw-r--r--Makefile.inc.in10
-rw-r--r--build.c132
-rw-r--r--build.h7
-rw-r--r--build/Makefile.in17
-rw-r--r--build/TODO44
-rw-r--r--build/build.c881
-rw-r--r--build/build.h33
-rw-r--r--build/files.c1800
-rw-r--r--build/files.h16
-rw-r--r--build/macro.c168
-rw-r--r--build/macro.h23
-rw-r--r--build/misc.c202
-rw-r--r--build/misc.h27
-rw-r--r--build/myftw.c20
-rw-r--r--build/myftw.h9
-rw-r--r--build/names.c15
-rw-r--r--build/names.h1
-rw-r--r--build/pack.c902
-rw-r--r--build/pack.h14
-rw-r--r--build/package.c128
-rw-r--r--build/package.h9
-rw-r--r--build/parse.h17
-rw-r--r--build/parseBuildInstallClean.c46
-rw-r--r--build/parseChangelog.c211
-rw-r--r--build/parseDescription.c110
-rw-r--r--build/parseFiles.c103
-rw-r--r--build/parsePreamble.c631
-rw-r--r--build/parsePrep.c480
-rw-r--r--build/parseReqs.c125
-rw-r--r--build/parseScript.c199
-rw-r--r--build/parseSpec.c186
-rw-r--r--build/parseTrigger.c (renamed from build/trigger.c)56
-rw-r--r--build/part.c56
-rw-r--r--build/part.h24
-rw-r--r--build/read.c138
-rw-r--r--build/read.h16
-rw-r--r--build/reqprov.c474
-rw-r--r--build/reqprov.h14
-rw-r--r--build/spec.c1857
-rw-r--r--build/spec.h130
-rw-r--r--build/specP.h97
-rw-r--r--build/trigger.h13
-rw-r--r--build/vspec.c206
-rw-r--r--lib/Makefile.in6
-rw-r--r--lib/misc.c2
-rwxr-xr-xrpm.c201
-rw-r--r--rpm.spec2
49 files changed, 5129 insertions, 4773 deletions
diff --git a/CHANGES b/CHANGES
index 68a6f778e..22dcc633b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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
diff --git a/Makefile.in b/Makefile.in
index 2e0abccc4..ecdb4fd44 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
diff --git a/Makefile.inc.in b/Makefile.inc.in
index 10c4cb8a3..fcc42e086 100644
--- a/Makefile.inc.in
+++ b/Makefile.inc.in
@@ -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@
diff --git a/build.c b/build.c
new file mode 100644
index 000000000..24c1d80a3
--- /dev/null
+++ b/build.c
@@ -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;
+}
diff --git a/build.h b/build.h
new file mode 100644
index 000000000..0cc4e3cb3
--- /dev/null
+++ b/build.h
@@ -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
diff --git a/build/Makefile.in b/build/Makefile.in
index 947268d10..29fdb0763 100644
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -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)
diff --git a/build/TODO b/build/TODO
new file mode 100644
index 000000000..14d0f4bbb
--- /dev/null
+++ b/build/TODO
@@ -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"
+_("...")
diff --git a/build/build.c b/build/build.c
index d432a0f5a..087737955 100644
--- a/build/build.c
+++ b/build/build.c
@@ -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 "misc.h"
#include "spec.h"
-#include "specP.h"
+#include "build.h"
+#include "lib/misc.h"
+#include "lib/messages.h"
#include "rpmlib.h"
-#include "messages.h"
-#include "stringbuf.h"
-#include "misc.h"
#include "pack.h"
-#include "popt/popt.h"
-#include "config.h"
-
-#include "names.h"
-
-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);
+#include "files.h"
-char build_subdir[1024];
+static void doRmSource(Spec spec);
+static int writeVars(Spec spec, FILE *f);
-struct Script *openScript(Spec spec, int builddir, char *name)
+int buildSpec(Spec spec, int what, 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");
+ int x, rc;
- 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");
+ 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 {
- 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)
-{
- 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);
- }
- 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);
+ if (what & RPMBUILD_PREP) {
+ if ((rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test))) {
+ return rc;
+ }
}
- 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);
+ if (what & RPMBUILD_BUILD) {
+ if ((rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test))) {
+ return rc;
+ }
}
-
- 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;
+ if (what & RPMBUILD_INSTALL) {
+ if ((rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test))) {
+ return rc;
+ }
}
- 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;
+ if (what & RPMBUILD_PACKAGESOURCE) {
+ if ((rc = processSourceFiles(spec))) {
+ return rc;
+ }
}
- 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);
+ if ((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
+ (what & RPMBUILD_FILECHECK)) {
+ if ((rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL))) {
+ return rc;
}
- } 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);
- }
+ }
+
+ if (what & RPMBUILD_PACKAGESOURCE) {
+ if ((rc = packageSources(spec))) {
+ return rc;
}
- 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);
+ }
+ if (what & RPMBUILD_PACKAGEBINARY) {
+ if ((rc = packageBinaries(spec))) {
+ return rc;
}
- } else {
- /* Must be a patch num */
- if (patch_index == 1024) {
- rpmError(RPMERR_BADSPEC, "Too many patches!");
- return(RPMERR_BADSPEC);
+ }
+
+ if (what & RPMBUILD_CLEAN) {
+ if ((rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test))) {
+ return rc;
}
- 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);
+ }
+ if (what & RPMBUILD_RMBUILD) {
+ if ((rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test))) {
+ return rc;
}
- 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);
+ if (what & RPMBUILD_RMSOURCE) {
+ doRmSource(spec);
}
- 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)
+int doScript(Spec spec, int what, char *name, StringBuf sb, int test)
{
- 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;
+ int fd;
+ FILE *f;
+ char *scriptName;
+ int pid;
+ int status;
+
+ 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;
+ }
+ if ((what != RPMBUILD_RMBUILD) && !sb) {
+ return 0;
}
-
- /* ... 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;
+
+ if (makeTempFile(NULL, &scriptName, &fd)) {
+ rpmError(RPMERR_SCRIPT, "Unable to open temp file");
+ return RPMERR_SCRIPT;
}
+ f = fdopen(fd, "w");
- return 0;
-}
-
-int execPrep(Spec s, int really_exec, int test)
-{
- char **lines, **lines1, *p;
- StringBuf out;
- int res;
-
- if (checkSources(s)) {
- return 1;
+ if (writeVars(spec, f)) {
+ fclose(f);
+ FREE(scriptName);
+ return RPMERR_SCRIPT;
}
- 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++;
+ 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);
- freeSplitString(lines1);
- res = 0;
- if (really_exec) {
- res = execPart(s, getStringBuf(out), "%prep", 0, test);
+ if (test) {
+ FREE(scriptName);
+ return 0;
}
- 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;
+
+ 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 ((res = finish_filelists(s))) {
- return res;
+ wait(&status);
+ if (! WIFEXITED(status) || WEXITSTATUS(status)) {
+ rpmError(RPMERR_SCRIPT, "Bad exit status from %s (%s)",
+ scriptName, name);
+ FREE(scriptName);
+ return RPMERR_SCRIPT;
}
- return execPart(s, getStringBuf(s->doc), "special doc", 1, test);
-}
+
+ unlink(scriptName);
+ FREE(scriptName);
-int execClean(Spec s)
-{
- return execPart(s, getStringBuf(s->clean), "%clean", 1, 0);
+ return 0;
}
-int verifyList(Spec s)
+static int writeVars(Spec spec, FILE *f)
{
- int res;
+ char *arch, *os, *s;
+
+ rpmGetArchInfo(&arch, NULL);
+ rpmGetOsInfo(&os, NULL);
- if ((res = finish_filelists(s))) {
- return res;
- }
- return packageBinaries(s, NULL, PACK_NOPACKAGE);
+ 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;
}
-int doBuild(Spec s, int flags, char *passPhrase)
+static void doRmSource(Spec spec)
{
- 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) {
- return 0;
- }
+ struct Source *p;
+ char buf[BUFSIZ];
- markBuildTime();
-
- if (flags & RPMBUILD_BINARY) {
- if (packageBinaries(s, passPhrase, PACK_PACKAGE)) {
- return 1;
- }
- if (execClean(s)) {
- return 1;
- }
- }
+ unlink(spec->specFile);
- if (flags & RPMBUILD_SOURCE) {
- if (packageSource(s, passPhrase)) {
- return 1;
+ p = spec->sources;
+ while (p) {
+ if (! (p->flags & RPMBUILD_ISNO)) {
+ sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), p->source);
+ unlink(buf);
}
+ p = p->next;
}
-
- if (flags & RPMBUILD_SWEEP) {
- doSweep(s);
- }
-
- if (flags & RPMBUILD_RMSOURCE) {
- doRmSource(s);
- }
-
- return 0;
}
diff --git a/build/build.h b/build/build.h
index aa984a5f3..62c27fe94 100644
--- a/build/build.h
+++ b/build/build.h
@@ -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);
-
-extern char build_subdir[1024];
+#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() */
-#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)
+int buildSpec(Spec spec, int what, int test);
-#endif _BUILD_H_
+int doScript(Spec spec, int what, char *name, StringBuf sb, int test);
diff --git a/build/files.c b/build/files.c
index 1159ff6f6..fe2023b40 100644
--- a/build/files.c
+++ b/build/files.c
@@ -1,651 +1,703 @@
-/* RPM - Copyright (C) 1995 Red Hat Software
- *
- * prepack.c - routines for packaging
- */
-
-#include "miscfn.h"
-
-#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <sys/stat.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <glob.h>
#include <time.h>
#include "spec.h"
-#include "specP.h"
-#include "stringbuf.h"
-#include "build.h"
-#include "messages.h"
-#include "md5.h"
+#include "package.h"
+#include "rpmlib.h"
+#include "misc.h"
+#include "lib/misc.h"
#include "myftw.h"
+#include "lib/cpio.h"
#include "header.h"
-#include "files.h"
+#include "md5.h"
#include "names.h"
-#include "rpmlead.h"
-#include "rpmlib.h"
-#include "misc.h"
+#include "messages.h"
#include "macro.h"
+#include "build.h"
-#define BINARY_HEADER 0
-#define SOURCE_HEADER 1
-
-struct file_entry {
- char file[1024];
- int isdoc;
- int conf;
- int isspecfile;
- int isghost;
- int verify_flags;
- char *uname; /* reference -- do not free */
- char *gname; /* reference -- do not free */
- struct stat statbuf;
- struct file_entry *next;
+#define MAXDOCDIR 1024
+
+struct FileListRec {
+ char *diskName; /* get file from here */
+ char *fileName; /* filename in cpio archive */
+ mode_t mode;
+ uid_t uid;
+ gid_t gid;
+ dev_t device;
+ ino_t inode;
+ char *uname;
+ char *gname;
+ int flags;
+ int verifyFlags;
+ int size;
+ int mtime;
+ dev_t rdev;
+ char *lang;
};
-static int add_file(struct file_entry **festack, const char *name,
- int isdoc, int isconf, int isdir, int isghost,
- int verify_flags,
- char *Pmode, char *Uname, char *Gname, char *prefix);
-static int compare_fe(const void *ap, const void *bp);
-static int add_file_aux(const char *file, struct stat *sb, int flag);
-static int glob_error(const char *foo, int bar);
-static int glob_pattern_p (char *pattern);
-static int parseForVerify(char *buf, int *verify_flags);
-static int parseForConfig(char *buf, int *conf);
-static int parseForAttr(char *origbuf, char **currPmode,
- char **currUname, char **currGname);
-
-static void resetDocdir(void);
-static void addDocdir(char *dirname);
-static int isDoc(char *filename);
+struct AttrRec {
+ char *PmodeString;
+ int Pmode;
+ char *PdirmodeString;
+ int Pdirmode;
+ char *Uname;
+ char *Gname;
+};
-static int processFileListFailed;
+struct FileList {
+ char *buildRoot;
+ char *prefix;
-static void parseForDocFiles(struct PackageRec *package, char *line)
-{
- if (! (line = strstr(line, "%doc"))) {
- return;
- }
+ int fileCount;
+ int totalFileSize;
+ int processingFailed;
- line += 4;
- if ((*line != ' ') && (*line != '\t')) {
- return;
- }
- line += strspn(line, " \t\n");
- if ((! *line) || (*line == '/')) {
- return;
- }
+ int passedSpecialDoc;
+ int isSpecialDoc;
- appendLineStringBuf(package->doc, "mkdir -p $DOCDIR");
- appendStringBuf(package->doc, "cp -pr ");
- appendStringBuf(package->doc, line);
- appendLineStringBuf(package->doc, " $DOCDIR");
-}
+ int isDir;
+ int inFtw;
+ int currentFlags;
+ int currentVerifyFlags;
+ struct AttrRec current;
+ struct AttrRec def;
+ int defVerifyFlags;
+ char *currentLang;
+
+ /* Hard coded limit of MAXDOCDIR docdirs. */
+ /* If you break it you are doing something wrong. */
+ char *docDirs[MAXDOCDIR];
+ int docDirCount;
+
+ struct FileListRec *fileList;
+ int fileListRecsAlloced;
+ int fileListRecsUsed;
+};
+
+static int processPackageFiles(Spec spec, Package pkg, int installSpecialDoc);
+static void freeFileList(struct FileListRec *fileList, int count);
+static int compareFileListRecs(const void *ap, const void *bp);
+static int isDoc(struct FileList *fl, char *fileName);
+static int processBinaryFile(Package pkg, struct FileList *fl, char *fileName);
+static int addFile(struct FileList *fl, char *name, struct stat *statp);
+static int parseForSimple(Spec spec, Package pkg, char *buf,
+ struct FileList *fl, char **fileName);
+static int parseForVerify(char *buf, struct FileList *fl);
+static int parseForLang(char *buf, struct FileList *fl);
+static int parseForAttr(char *buf, struct FileList *fl);
+static int parseForConfig(char *buf, struct FileList *fl);
+static int myGlobPatternP(char *pattern);
+static int glob_error(const char *foo, int bar);
+static void timeCheck(int tc, Header h);
+static void genCpioListAndHeader(struct FileList *fl,
+ struct cpioFileMapping **cpioList,
+ int *cpioCount, Header h, int isSrc);
-int finish_filelists(Spec spec)
+int processSourceFiles(Spec spec)
{
- char buf[1024];
- FILE *file;
- struct PackageRec *pr = spec->packages;
- char *s, **files, **line;
- char *version, *release, *packageVersion, *docs, *name;
-
- headerGetEntry(spec->packages->header, RPMTAG_VERSION, NULL,
- (void *) &version, NULL);
- headerGetEntry(spec->packages->header, RPMTAG_RELEASE, NULL,
- (void *) &release, NULL);
-
- while (pr) {
- if (pr->fileFile) {
- sprintf(buf, "%s/%s/%s", rpmGetVar(RPMVAR_BUILDDIR),
- build_subdir, pr->fileFile);
- rpmMessage(RPMMESS_DEBUG, "Reading file names from: %s\n", buf);
- if ((file = fopen(buf, "r")) == NULL) {
- rpmError(RPMERR_BADSPEC, "unable to open filelist: %s\n", buf);
- return(RPMERR_BADSPEC);
+ struct Source *srcPtr;
+ char buf[BUFSIZ];
+ StringBuf sourceFiles;
+ int x, isSpec = 1;
+ struct FileList fl;
+ char *s, **files, **fp, *fn;
+ struct stat sb;
+ HeaderIterator hi;
+ int tag, type, count;
+ void * ptr;
+
+ sourceFiles = newStringBuf();
+ spec->sourceHeader = headerNew();
+
+ /* Only specific tags are added to the source package header */
+ hi = headerInitIterator(spec->packages->header);
+ while (headerNextIterator(hi, &tag, &type, &ptr, &count)) {
+ switch (tag) {
+ case RPMTAG_NAME:
+ case RPMTAG_VERSION:
+ case RPMTAG_RELEASE:
+ case RPMTAG_SERIAL:
+ case RPMTAG_SUMMARY:
+ case RPMTAG_DESCRIPTION:
+ case RPMTAG_PACKAGER:
+ case RPMTAG_DISTRIBUTION:
+ case RPMTAG_VENDOR:
+ case RPMTAG_COPYRIGHT:
+ case RPMTAG_GROUP:
+ case RPMTAG_OS:
+ case RPMTAG_ARCH:
+ case RPMTAG_CHANGELOGTIME:
+ case RPMTAG_CHANGELOGNAME:
+ case RPMTAG_CHANGELOGTEXT:
+ case RPMTAG_URL:
+ headerAddEntry(spec->sourceHeader, tag, type, ptr, count);
+ break;
+ default:
+ /* do not copy */
+ break;
+ }
+ if (type == RPM_STRING_ARRAY_TYPE) {
+ FREE(ptr);
+ }
+ }
+ headerFreeIterator(hi);
+
+ /* Construct the file list and source entries */
+ appendLineStringBuf(sourceFiles, spec->specFile);
+ srcPtr = spec->sources;
+ while (srcPtr) {
+ if (srcPtr->flags & RPMBUILD_ISSOURCE) {
+ headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_SOURCE,
+ RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
+ if (srcPtr->flags & RPMBUILD_ISNO) {
+ headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOSOURCE,
+ RPM_INT32_TYPE, &srcPtr->num, 1);
}
- while (fgets(buf, sizeof(buf), file)) {
- expandMacros(buf);
- appendStringBuf(pr->filelist, buf);
+ }
+ if (srcPtr->flags & RPMBUILD_ISPATCH) {
+ headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_PATCH,
+ RPM_STRING_ARRAY_TYPE, &srcPtr->source, 1);
+ if (srcPtr->flags & RPMBUILD_ISNO) {
+ headerAddOrAppendEntry(spec->sourceHeader, RPMTAG_NOPATCH,
+ RPM_INT32_TYPE, &srcPtr->num, 1);
}
- fclose(file);
}
+ sprintf(buf, "%s%s/%s",
+ srcPtr->flags & RPMBUILD_ISNO ? "!" : "",
+ rpmGetVar(RPMVAR_SOURCEDIR), srcPtr->source);
+ appendLineStringBuf(sourceFiles, buf);
+ srcPtr = srcPtr->next;
+ }
+
+ spec->sourceCpioList = NULL;
+ spec->sourceCpioCount = 0;
- /* parse for %doc wierdness */
- s = getStringBuf(pr->filelist);
- files = splitString(s, strlen(s), '\n');
- line = files;
- while (*line) {
- parseForDocFiles(pr, *line);
- line++;
+ fl.fileList = malloc((spec->numSources + 1) * sizeof(struct FileListRec));
+ fl.processingFailed = 0;
+ fl.fileListRecsUsed = 0;
+ fl.totalFileSize = 0;
+ fl.prefix = NULL;
+
+ s = getStringBuf(sourceFiles);
+ files = splitString(s, strlen(s), '\n');
+ fp = files;
+
+ /* The first source file is the spec file */
+ x = 0;
+ while (*fp) {
+ s = *fp;
+ SKIPSPACE(s);
+ if (! *s) {
+ fp++; continue;
}
- freeSplitString(files);
- /* Handle subpackage version overrides */
- if (!headerGetEntry(pr->header, RPMTAG_VERSION, NULL,
- (void *) &packageVersion, NULL)) {
- packageVersion = version;
+ fl.fileList[x].flags = isSpec ? RPMFILE_SPECFILE : 0;
+ /* files with leading ! are no source files */
+ if (*s == '!') {
+ fl.fileList[x].flags |= RPMFILE_GHOST;
+ s++;
+ }
+ fl.fileList[x].diskName = strdup(s);
+ fn = strrchr(s, '/');
+ if (fn) {
+ fn++;
+ } else {
+ fn = s;
}
+ fl.fileList[x].fileName = strdup(fn);
+ fl.fileList[x].verifyFlags = RPMVERIFY_ALL;
+ lstat(s, &sb);
+ fl.fileList[x].mode = sb.st_mode;
+ fl.fileList[x].uid = sb.st_uid;
+ fl.fileList[x].gid = sb.st_gid;
+ fl.fileList[x].uname = getUname(sb.st_uid);
+ fl.fileList[x].gname = getGname(sb.st_gid);
+ fl.fileList[x].size = sb.st_size;
+ fl.fileList[x].mtime = sb.st_mtime;
+ fl.fileList[x].rdev = sb.st_rdev;
+ fl.fileList[x].device = sb.st_dev;
+ fl.fileList[x].inode = sb.st_ino;
+ fl.fileList[x].lang = strdup("");
+
+ fl.totalFileSize += sb.st_size;
+
+ if (! (fl.fileList[x].uname && fl.fileList[x].gname)) {
+ rpmError(RPMERR_BADSPEC, "Bad owner/group: %s", s);
+ fl.processingFailed = 1;
+ }
+
+ isSpec = 0;
+ fp++;
+ x++;
+ }
+ fl.fileListRecsUsed = x;
+ FREE(files);
- /* Generate the doc script */
- appendStringBuf(spec->doc, "DOCDIR=$RPM_ROOT_DIR/$RPM_DOC_DIR/");
- headerGetEntry(pr->header, RPMTAG_NAME, NULL, (void *) &name, NULL);
- sprintf(buf, "%s-%s", name, packageVersion);
- appendLineStringBuf(spec->doc, buf);
- docs = getStringBuf(pr->doc);
- if (*docs) {
- appendLineStringBuf(spec->doc, "rm -rf $DOCDIR");
- appendLineStringBuf(spec->doc, docs);
+ if (! fl.processingFailed) {
+ genCpioListAndHeader(&fl, &(spec->sourceCpioList),
+ &(spec->sourceCpioCount), spec->sourceHeader, 1);
+ }
+
+ freeStringBuf(sourceFiles);
+ freeFileList(fl.fileList, fl.fileListRecsUsed);
+ return fl.processingFailed;
+}
+
+int processBinaryFiles(Spec spec, int installSpecialDoc)
+{
+ Package pkg;
+ int rc;
+
+ pkg = spec->packages;
+ while (pkg) {
+ if (!pkg->fileList) {
+ pkg = pkg->next;
+ continue;
+ }
+
+ if ((rc = processPackageFiles(spec, pkg, installSpecialDoc))) {
+ return rc;
}
- pr = pr->next;
+ pkg = pkg->next;
}
return 0;
}
-int process_filelist(Header header, struct PackageRec *pr,
- StringBuf sb, int *size, char *name,
- char *version, char *release, int type,
- char *prefix, char *specFile)
+static int processPackageFiles(Spec spec, Package pkg, int installSpecialDoc)
{
- char buf[1024];
- char **files, **fp;
- struct file_entry *fes, *fest;
- struct file_entry **file_entry_array;
- int isdoc, conf, isdir, verify_flags, isghost;
- char *currPmode=NULL; /* hold info from %attr() */
- char *currUname=NULL; /* hold info from %attr() */
- char *currGname=NULL; /* hold info from %attr() */
- char *filename, *s;
- char *str;
- int count = 0;
- int c, x;
- glob_t glob_result;
- int special_doc;
- int passed_special_doc = 0;
- int tc;
- char *tcs;
- int currentTime;
+ struct FileList fl;
+ char *s, **files, **fp, *fileName;
+ char buf[BUFSIZ];
+ FILE *f;
- processFileListFailed = 0;
- fes = NULL;
- *size = 0;
+ struct AttrRec specialDocAttrRec;
+ char *specialDoc = NULL;
+
+ pkg->cpioList = NULL;
+ pkg->cpioCount = 0;
+
+ if (pkg->fileFile) {
+ sprintf(buf, "%s/%s/%s", rpmGetVar(RPMVAR_BUILDDIR),
+ spec->buildSubdir, pkg->fileFile);
+ if ((f = fopen(buf, "r")) == NULL) {
+ rpmError(RPMERR_BADFILENAME,
+ "Could not open %%files file: %s", pkg->fileFile);
+ return RPMERR_BADFILENAME;
+ }
+ while (fgets(buf, sizeof(buf), f)) {
+ expandMacros(&spec->macros, buf);
+ appendStringBuf(pkg->fileList, buf);
+ }
+ fclose(f);
+ }
+
+ /* Init the file list structure */
+
+ fl.buildRoot = spec->buildRoot ? spec->buildRoot : "";
+ if (headerGetEntry(pkg->header, RPMTAG_DEFAULTPREFIX,
+ NULL, (void *)&fl.prefix, NULL)) {
+ fl.prefix = strdup(fl.prefix);
+ } else {
+ fl.prefix = NULL;
+ }
- resetDocdir();
+ fl.fileCount = 0;
+ fl.totalFileSize = 0;
+ fl.processingFailed = 0;
- str = getStringBuf(sb);
- files = splitString(str, strlen(str), '\n');
+ fl.passedSpecialDoc = 0;
+
+ fl.current.PmodeString = NULL;
+ fl.current.PdirmodeString = NULL;
+ fl.current.Uname = NULL;
+ fl.current.Gname = NULL;
+ fl.def.PmodeString = NULL;
+ fl.def.PdirmodeString = NULL;
+ fl.def.Uname = NULL;
+ fl.def.Gname = NULL;
+ fl.currentLang = NULL;
+
+ fl.defVerifyFlags = RPMVERIFY_ALL;
+
+ fl.docDirCount = 0;
+ fl.docDirs[fl.docDirCount++] = strdup("/usr/doc");
+ fl.docDirs[fl.docDirCount++] = strdup("/usr/man");
+ fl.docDirs[fl.docDirCount++] = strdup("/usr/info");
+ fl.docDirs[fl.docDirCount++] = strdup("/usr/X11R6/man");
+ fl.docDirs[fl.docDirCount++] = strdup(spec->docDir);
+
+ fl.fileList = NULL;
+ fl.fileListRecsAlloced = 0;
+ fl.fileListRecsUsed = 0;
+
+ s = getStringBuf(pkg->fileList);
+ files = splitString(s, strlen(s), '\n');
fp = files;
while (*fp) {
- strcpy(buf, *fp); /* temp copy */
- isdoc = 0;
- special_doc = 0;
- conf = 0;
- isdir = 0;
- isghost = 0;
- if (currPmode) {
- free (currPmode);
- currPmode = NULL;
- }
- if (currUname) {
- free (currUname);
- currUname = NULL;
- }
- if (currGname) {
- free (currGname);
- currGname = NULL;
- }
- verify_flags = RPMVERIFY_ALL;
- filename = NULL;
-
- /* First preparse buf for %verify() */
- if (parseForVerify(buf, &verify_flags)) {
- processFileListFailed = 1;
+ s = *fp;
+ SKIPSPACE(s);
+ if (! *s) {
fp++; continue;
}
+ fileName = NULL;
+ strcpy(buf, s);
- /* Next parse for %attr() */
- if (parseForAttr(buf, &currPmode, &currUname, &currGname)) {
- processFileListFailed = 1;
- fp++; continue;
+ /* Reset for a new line in %files */
+ fl.isDir = 0;
+ fl.inFtw = 0;
+ fl.currentFlags = 0;
+ fl.currentVerifyFlags = fl.defVerifyFlags;
+ fl.current.Pmode = fl.def.Pmode;
+ fl.current.Pdirmode = fl.def.Pdirmode;
+ fl.isSpecialDoc = 0;
+ FREE(fl.current.PmodeString);
+ FREE(fl.current.PdirmodeString);
+ FREE(fl.current.Uname);
+ FREE(fl.current.Gname);
+ FREE(fl.currentLang);
+ if (fl.def.PmodeString) {
+ fl.current.PmodeString = strdup(fl.def.PmodeString);
+ }
+ if (fl.def.PdirmodeString) {
+ fl.current.PdirmodeString = strdup(fl.def.PdirmodeString);
+ }
+ if (fl.def.Uname) {
+ fl.current.Uname = strdup(fl.def.Uname);
+ }
+ if (fl.def.Gname) {
+ fl.current.Gname = strdup(fl.def.Gname);
}
- /* Then parse for %config or %config() */
- if (parseForConfig(buf, &conf)) {
- processFileListFailed = 1;
+ if (parseForVerify(buf, &fl)) {
fp++; continue;
}
-
- s = strtok(buf, " \t\n");
- while (s) {
- if (!strcmp(s, "%docdir")) {
- s = strtok(NULL, " \t\n");
- addDocdir(s);
- break;
- } else if (!strcmp(s, "%doc")) {
- isdoc = 1;
- } else if (!strcmp(s, "%dir")) {
- isdir = 1;
- } else if (!strcmp(s, "%ghost")) {
- isghost = 1;
- } else {
- if (filename) {
- /* We already got a file -- error */
- rpmError(RPMERR_BADSPEC,
- "Two files on one line: %s", filename);
- processFileListFailed = 1;
- }
- if (*s != '/') {
- if (isdoc) {
- special_doc = 1;
- } else {
- /* not in %doc, does not begin with / -- error */
- rpmError(RPMERR_BADSPEC,
- "File must begin with \"/\": %s", s);
- processFileListFailed = 1;
- }
- } else {
- filename = s;
- }
- }
- s = strtok(NULL, " \t\n");
+ if (parseForAttr(buf, &fl)) {
+ fp++; continue;
}
- if (special_doc) {
- if (passed_special_doc) {
- fp++;
- continue;
- } else {
- if (filename || conf || isdir || isghost) {
- rpmError(RPMERR_BADSPEC,
- "Can't mix special %%doc with other forms: %s", fp);
- processFileListFailed = 1;
- fp++; continue;
- }
- sprintf(buf, "%s/%s-%s", rpmGetVar(RPMVAR_DEFAULTDOCDIR),
- name, version);
- filename = buf;
- passed_special_doc = 1;
- }
+ if (parseForConfig(buf, &fl)) {
+ fp++; continue;
}
- if (! filename) {
- fp++;
- continue;
+ if (parseForLang(buf, &fl)) {
+ fp++; continue;
+ }
+ if (parseForSimple(spec, pkg, buf, &fl, &fileName)) {
+ fp++; continue;
+ }
+ if (! fileName) {
+ fp++; continue;
}
- if (type == RPMLEAD_BINARY) {
- /* check that file starts with leading "/" */
- if (*filename != '/') {
- rpmError(RPMERR_BADSPEC,
- "File needs leading \"/\": %s", filename);
- processFileListFailed = 1;
- fp++; continue;
+ if (fl.isSpecialDoc) {
+ /* Save this stuff for last */
+ specialDoc = strdup(fileName);
+ specialDocAttrRec = fl.current;
+ if (specialDocAttrRec.PmodeString) {
+ specialDocAttrRec.PmodeString =
+ strdup(specialDocAttrRec.PmodeString);
}
-
- if (glob_pattern_p(filename)) {
- char fullname[1024];
-
- if (rpmGetVar(RPMVAR_ROOT)) {
- sprintf(fullname, "%s%s", rpmGetVar(RPMVAR_ROOT), filename);
- } else {
- strcpy(fullname, filename);
- }
-
- if (glob(fullname, 0, glob_error, &glob_result) ||
- (glob_result.gl_pathc < 1)) {
- rpmError(RPMERR_BADSPEC, "No matches: %s", fullname);
- processFileListFailed = 1;
- globfree(&glob_result);
- fp++; continue;
- }
-
- c = 0;
- x = 0;
- while (x < glob_result.gl_pathc) {
- int offset = strlen(rpmGetVar(RPMVAR_ROOT) ? : "");
- c += add_file(&fes, &(glob_result.gl_pathv[x][offset]),
- isdoc, conf, isdir, isghost, verify_flags,
- currPmode, currUname, currGname, prefix);
- x++;
- }
- globfree(&glob_result);
- } else {
- c = add_file(&fes, filename, isdoc, conf, isdir, isghost,
- verify_flags, currPmode, currUname,
- currGname, prefix);
+ if (specialDocAttrRec.PdirmodeString) {
+ specialDocAttrRec.PdirmodeString =
+ strdup(specialDocAttrRec.PdirmodeString);
}
- } else {
- /* Source package are the simple case */
- fest = malloc(sizeof(struct file_entry));
- fest->isdoc = 0;
- fest->conf = 0;
- fest->isghost = 0;
- if (!strcmp(filename, specFile)) {
- fest->isspecfile = 1;
- } else {
- fest->isspecfile = 0;
+ if (specialDocAttrRec.Uname) {
+ specialDocAttrRec.Uname = strdup(specialDocAttrRec.Uname);
}
- fest->verify_flags = 0; /* XXX - something else? */
- stat(filename, &fest->statbuf);
- fest->uname = getUname(fest->statbuf.st_uid);
- fest->gname = getGname(fest->statbuf.st_gid);
- if (! (fest->uname && fest->gname)) {
- rpmError(RPMERR_BADSPEC, "Bad owner/group: %s", filename);
- fest->uname = "";
- fest->gname = "";
- processFileListFailed = 1;
+ if (specialDocAttrRec.Gname) {
+ specialDocAttrRec.Gname = strdup(specialDocAttrRec.Gname);
}
- strcpy(fest->file, filename);
- fest->next = fes;
- fes = fest;
- c = 1;
- }
-
- if (! c) {
- rpmError(RPMERR_BADSPEC, "File not found: %s", filename);
- processFileListFailed = 1;
+ } else {
+ processBinaryFile(pkg, &fl, fileName);
}
- count += c;
fp++;
}
- /* If there are no files, don't add anything to the header */
- if (count) {
- char ** fileList;
- char ** fileMD5List;
- char ** fileLinktoList;
- int_32 * fileSizeList;
- int_32 * fileUIDList;
- int_32 * fileGIDList;
- char ** fileUnameList;
- char ** fileGnameList;
- int_32 * fileMtimesList;
- int_32 * fileFlagsList;
- int_16 * fileModesList;
- int_16 * fileRDevsList;
- int_32 * fileVerifyFlagsList;
-
- fileList = malloc(sizeof(char *) * count);
- fileLinktoList = malloc(sizeof(char *) * count);
- fileMD5List = malloc(sizeof(char *) * count);
- fileSizeList = malloc(sizeof(int_32) * count);
- fileUIDList = malloc(sizeof(int_32) * count);
- fileGIDList = malloc(sizeof(int_32) * count);
- fileUnameList = malloc(sizeof(char *) * count);
- fileGnameList = malloc(sizeof(char *) * count);
- fileMtimesList = malloc(sizeof(int_32) * count);
- fileFlagsList = malloc(sizeof(int_32) * count);
- fileModesList = malloc(sizeof(int_16) * count);
- fileRDevsList = malloc(sizeof(int_16) * count);
- fileVerifyFlagsList = malloc(sizeof(int_32) * count);
-
- /* Build a reverse sorted file array. */
- /* This makes uninstalls a lot easier. */
- file_entry_array = malloc(sizeof(struct file_entry *) * count);
- c = 0;
- fest = fes;
- while (fest) {
- file_entry_array[c++] = fest;
- fest = fest->next;
- }
- qsort(file_entry_array, count, sizeof(struct file_entry *),
- compare_fe);
-
- /* Do timecheck */
- tc = 0;
- currentTime = time(NULL);
- if ((tcs = rpmGetVar(RPMVAR_TIMECHECK))) {
- tc = strtoul(tcs, NULL, 10);
+ /* Now process special doc, if there is one */
+ if (specialDoc) {
+ if (installSpecialDoc) {
+ doScript(spec, RPMBUILD_STRINGBUF, "%doc", pkg->specialDoc, 0);
}
+ fl.current = specialDocAttrRec;
+ processBinaryFile(pkg, &fl, specialDoc);
+ FREE(specialDoc);
+ FREE(specialDocAttrRec.PmodeString);
+ FREE(specialDocAttrRec.PdirmodeString);
+ FREE(specialDocAttrRec.Uname);
+ FREE(specialDocAttrRec.Gname);
+ }
- c = 0;
- while (c < count) {
- fest = file_entry_array[c];
- if (type == RPMLEAD_BINARY) {
- x = strlen(fest->file) - 1;
- if (x && fest->file[x] == '/') {
- fest->file[x] = '\0';
- }
- fileList[c] = fest->file;
- } else {
- fileList[c] = strrchr(fest->file, '/') + 1;
- }
- if ((c > 0) && !strcmp(fileList[c], fileList[c-1])) {
- rpmError(RPMERR_BADSPEC, "File listed twice: %s", fileList[c]);
- processFileListFailed = 1;
- }
-
- fileUnameList[c] = fest->uname;
- fileGnameList[c] = fest->gname;
- *size += fest->statbuf.st_size;
- if (S_ISREG(fest->statbuf.st_mode)) {
- if ((type == RPMLEAD_BINARY) &&
- rpmGetVar(RPMVAR_ROOT)) {
- sprintf(buf, "%s%s", rpmGetVar(RPMVAR_ROOT), fest->file);
- } else {
- strcpy(buf, fest->file);
- }
- mdfile(buf, buf);
- fileMD5List[c] = strdup(buf);
- rpmMessage(RPMMESS_DEBUG, "md5(%s) = %s\n", fest->file, buf);
- } else {
- /* This is stupid */
- fileMD5List[c] = strdup("");
- }
- fileSizeList[c] = fest->statbuf.st_size;
- fileUIDList[c] = fest->statbuf.st_uid;
- fileGIDList[c] = fest->statbuf.st_gid;
- fileMtimesList[c] = fest->statbuf.st_mtime;
-
- /* Do timecheck */
- if (tc && (type == RPMLEAD_BINARY)) {
- if (currentTime - fest->statbuf.st_mtime > tc) {
- rpmMessage(RPMMESS_WARNING, "TIMECHECK failure: %s\n",
- fest->file);
- }
- }
-
- fileFlagsList[c] = 0;
- if (isDoc(fest->file))
- fileFlagsList[c] |= RPMFILE_DOC;
- if (fest->isdoc)
- fileFlagsList[c] |= RPMFILE_DOC;
- if (fest->isghost)
- fileFlagsList[c] |= RPMFILE_GHOST;
- if (fest->conf && !(fest->statbuf.st_mode & S_IFDIR))
- fileFlagsList[c] |= fest->conf;
- if (fest->isspecfile)
- fileFlagsList[c] |= RPMFILE_SPECFILE;
-
- fileModesList[c] = fest->statbuf.st_mode;
- fileRDevsList[c] = fest->statbuf.st_rdev;
- if (! fest->isghost) {
- fileVerifyFlagsList[c] = fest->verify_flags;
- } else {
- fileVerifyFlagsList[c] = fest->verify_flags &
- ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
- RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
- }
+ FREE(files);
- if (S_ISLNK(fest->statbuf.st_mode)) {
- if (rpmGetVar(RPMVAR_ROOT)) {
- sprintf(buf, "%s%s", rpmGetVar(RPMVAR_ROOT), fest->file);
- } else {
- strcpy(buf, fest->file);
- }
- buf[readlink(buf, buf, 1024)] = '\0';
- fileLinktoList[c] = strdup(buf);
- } else {
- /* This is stupid */
- fileLinktoList[c] = strdup("");
- }
- c++;
- }
-
- /* Add the header entries */
- c = count;
- headerAddEntry(header, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE, fileList, c);
- headerAddEntry(header, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
- fileLinktoList, c);
- headerAddEntry(header, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE, fileMD5List, c);
- headerAddEntry(header, RPMTAG_FILESIZES, RPM_INT32_TYPE, fileSizeList, c);
- headerAddEntry(header, RPMTAG_FILEUIDS, RPM_INT32_TYPE, fileUIDList, c);
- headerAddEntry(header, RPMTAG_FILEGIDS, RPM_INT32_TYPE, fileGIDList, c);
- headerAddEntry(header, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
- fileUnameList, c);
- headerAddEntry(header, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
- fileGnameList, c);
- headerAddEntry(header, RPMTAG_FILEMTIMES, RPM_INT32_TYPE, fileMtimesList, c);
- headerAddEntry(header, RPMTAG_FILEFLAGS, RPM_INT32_TYPE, fileFlagsList, c);
- headerAddEntry(header, RPMTAG_FILEMODES, RPM_INT16_TYPE, fileModesList, c);
- headerAddEntry(header, RPMTAG_FILERDEVS, RPM_INT16_TYPE, fileRDevsList, c);
- headerAddEntry(header, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
- fileVerifyFlagsList, c);
-
- /* Free the allocated strings */
- c = count;
- while (c--) {
- free(fileMD5List[c]);
- free(fileLinktoList[c]);
- }
-
- /* Free all those lists */
- free(fileList);
- free(fileLinktoList);
- free(fileMD5List);
- free(fileSizeList);
- free(fileUIDList);
- free(fileGIDList);
- free(fileUnameList);
- free(fileGnameList);
- free(fileMtimesList);
- free(fileFlagsList);
- free(fileModesList);
- free(fileRDevsList);
- free(fileVerifyFlagsList);
-
- /* Free the file entry array */
- free(file_entry_array);
-
- /* Free the file entry stack */
- fest = fes;
- while (fest) {
- fes = fest->next;
- free(fest);
- fest = fes;
+ if (! fl.processingFailed) {
+ genCpioListAndHeader(&fl, &(pkg->cpioList), &(pkg->cpioCount),
+ pkg->header, 0);
+
+ if (spec->timeCheck) {
+ timeCheck(spec->timeCheck, pkg->header);
}
}
- freeSplitString(files);
- return processFileListFailed;
+ /* Clean up */
+ FREE(fl.prefix);
+ FREE(fl.current.PmodeString);
+ FREE(fl.current.PdirmodeString);
+ FREE(fl.current.Uname);
+ FREE(fl.current.Gname);
+ FREE(fl.def.PmodeString);
+ FREE(fl.def.PdirmodeString);
+ FREE(fl.def.Uname);
+ FREE(fl.def.Gname);
+ FREE(fl.currentLang);
+ freeFileList(fl.fileList, fl.fileListRecsUsed);
+ while (fl.docDirCount--) {
+ FREE(fl.docDirs[fl.docDirCount]);
+ }
+ return fl.processingFailed;
}
-/*************************************************************/
-/* */
-/* misc */
-/* */
-/*************************************************************/
-
-static int compare_fe(const void *ap, const void *bp)
+static void timeCheck(int tc, Header h)
{
- char *a, *b;
+ int *mtime;
+ char **file;
+ int count, x, currentTime;
- a = (*(struct file_entry **)ap)->file;
- b = (*(struct file_entry **)bp)->file;
+ headerGetEntry(h, RPMTAG_FILENAMES, NULL, (void **) &file, &count);
+ headerGetEntry(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtime, NULL);
- return strcmp(a, b);
+ currentTime = time(NULL);
+
+ x = 0;
+ while (x < count) {
+ if (currentTime - mtime[x] > tc) {
+ rpmMessage(RPMMESS_WARNING, "TIMECHECK failure: %s\n", file[x]);
+ }
+ x++;
+ }
}
-/*************************************************************/
-/* */
-/* Doc dir stuff */
-/* */
-/*************************************************************/
-
-/* XXX hard coded limit -- only 1024 %docdir allowed */
-static char *docdirs[1024];
-static int docdir_count;
+static void genCpioListAndHeader(struct FileList *fl,
+ struct cpioFileMapping **cpioList,
+ int *cpioCount, Header h, int isSrc)
+{
+ int skipLen = 0;
+ struct FileListRec *p;
+ int count;
+ struct cpioFileMapping *cpioListPtr;
+ char *s, buf[BUFSIZ];
+
+ /* Sort the big list */
+ qsort(fl->fileList, fl->fileListRecsUsed,
+ sizeof(*(fl->fileList)), compareFileListRecs);
+
+ /* Generate the cpio list and the header */
+ if (! isSrc) {
+ if (fl->prefix) {
+ skipLen = 1 + strlen(fl->prefix);
+ } else {
+ skipLen = 1;
+ }
+ }
+ *cpioList = malloc(sizeof(**cpioList) * fl->fileListRecsUsed);
+ *cpioCount = 0;
+ cpioListPtr = *cpioList;
+ p = fl->fileList;
+ count = fl->fileListRecsUsed;
+ while (count) {
+ if ((count > 1) && !strcmp(p->fileName, p[1].fileName)) {
+ rpmError(RPMERR_BADSPEC, "File listed twice: %s", p->fileName);
+ fl->processingFailed = 1;
+ }
+
+ /* Make the cpio list */
+ if (! (p->flags & RPMFILE_GHOST)) {
+ cpioListPtr->fsPath = strdup(p->diskName);
+ cpioListPtr->archivePath = strdup(p->fileName + skipLen);
+ cpioListPtr->finalMode = p->mode;
+ cpioListPtr->finalUid = p->uid;
+ cpioListPtr->finalGid = p->gid;
+ cpioListPtr->mapFlags = CPIO_MAP_PATH | CPIO_MAP_MODE |
+ CPIO_MAP_UID | CPIO_MAP_GID;
+ cpioListPtr++;
+ (*cpioCount)++;
+ }
+
+ /* Make the header */
+ headerAddOrAppendEntry(h, RPMTAG_FILENAMES, RPM_STRING_ARRAY_TYPE,
+ &(p->fileName), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
+ &(p->size), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEUSERNAME, RPM_STRING_ARRAY_TYPE,
+ &(p->uname), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEGROUPNAME, RPM_STRING_ARRAY_TYPE,
+ &(p->gname), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
+ &(p->mtime), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEMODES, RPM_INT16_TYPE,
+ &(p->mode), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILERDEVS, RPM_INT16_TYPE,
+ &(p->rdev), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEDEVICES, RPM_INT32_TYPE,
+ &(p->device), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILEINODES, RPM_INT32_TYPE,
+ &(p->inode), 1);
+ headerAddOrAppendEntry(h, RPMTAG_FILELANGS, RPM_STRING_ARRAY_TYPE,
+ &(p->lang), 1);
+
+ /* We used to add these, but they should not be needed */
+ /* headerAddOrAppendEntry(h, RPMTAG_FILEUIDS,
+ * RPM_INT32_TYPE, &(p->uid), 1);
+ * headerAddOrAppendEntry(h, RPMTAG_FILEGIDS,
+ * RPM_INT32_TYPE, &(p->gid), 1);
+ */
+
+ buf[0] = '\0';
+ s = buf;
+ if (S_ISREG(p->mode)) {
+ mdfile(p->diskName, buf);
+ }
+ headerAddOrAppendEntry(h, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE,
+ &s, 1);
+
+ buf[0] = '\0';
+ s = buf;
+ if (S_ISLNK(p->mode)) {
+ buf[readlink(p->diskName, buf, BUFSIZ)] = '\0';
+ }
+ headerAddOrAppendEntry(h, RPMTAG_FILELINKTOS, RPM_STRING_ARRAY_TYPE,
+ &s, 1);
+
+ if (p->flags & RPMFILE_GHOST) {
+ p->verifyFlags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE |
+ RPMVERIFY_LINKTO | RPMVERIFY_MTIME);
+ }
+ headerAddOrAppendEntry(h, RPMTAG_FILEVERIFYFLAGS, RPM_INT32_TYPE,
+ &(p->verifyFlags), 1);
+
+ if (!isSrc && isDoc(fl, p->fileName)) {
+ p->flags |= RPMFILE_DOC;
+ }
+ if (p->mode & S_IFDIR) {
+ p->flags &= ~RPMFILE_CONFIG;
+ p->flags &= ~RPMFILE_DOC;
+ }
+ headerAddOrAppendEntry(h, RPMTAG_FILEFLAGS, RPM_INT32_TYPE,
+ &(p->flags), 1);
+
+ p++;
+ count--;
+ }
+ headerAddEntry(h, RPMTAG_SIZE, RPM_INT32_TYPE,
+ &(fl->totalFileSize), 1);
+}
-static void resetDocdir(void)
+static void freeFileList(struct FileListRec *fileList, int count)
{
- while (docdir_count--) {
- free(docdirs[docdir_count]);
- }
- docdir_count = 0;
- docdirs[docdir_count++] = strdup("/usr/doc");
- docdirs[docdir_count++] = strdup("/usr/man");
- docdirs[docdir_count++] = strdup("/usr/info");
- docdirs[docdir_count++] = strdup("/usr/X11R6/man");
+ while (count--) {
+ FREE(fileList[count].diskName);
+ FREE(fileList[count].fileName);
+ FREE(fileList[count].lang);
+ }
+ FREE(fileList);
}
-static void addDocdir(char *dirname)
+void freeCpioList(struct cpioFileMapping *cpioList, int cpioCount)
{
- if (docdir_count == 1024) {
- fprintf(stderr, "RPMERR_INTERNAL: Hit limit in addDocdir()\n");
- exit(RPMERR_INTERNAL);
+ struct cpioFileMapping *p = cpioList;
+
+ while (cpioCount--) {
+ rpmMessage(RPMMESS_DEBUG, "archive = %s, fs = %s\n",
+ p->archivePath, p->fsPath);
+ FREE(p->archivePath);
+ FREE(p->fsPath);
+ p++;
}
- docdirs[docdir_count++] = strdup(dirname);
+ FREE(cpioList);
+}
+
+static int compareFileListRecs(const void *ap, const void *bp)
+{
+ char *a, *b;
+
+ a = ((struct FileListRec *)ap)->fileName;
+ b = ((struct FileListRec *)bp)->fileName;
+
+ return strcmp(a, b);
}
-static int isDoc(char *filename)
+static int isDoc(struct FileList *fl, char *fileName)
{
- int x = 0;
+ int x = fl->docDirCount;
- while (x < docdir_count) {
- if (strstr(filename, docdirs[x]) == filename) {
+ while (x--) {
+ if (strstr(fileName, fl->docDirs[x]) == fileName) {
return 1;
}
- x++;
}
return 0;
}
-/*************************************************************/
-/* */
-/* File stating / tree walk */
-/* */
-/*************************************************************/
-
-/* Need a bunch of globals to keep track of things in ftw() */
-static int Gisdoc;
-static int Gisghost;
-static int Gconf;
-static int Gverify_flags;
-static int Gcount;
-static char *GPmode;
-static char *GUname;
-static char *GGname;
-static struct file_entry **Gfestack;
-static char *Gprefix;
-
-static int add_file(struct file_entry **festack, const char *name,
- int isdoc, int conf, int isdir, int isghost,
- int verify_flags,
- char *Pmode, char *Uname, char *Gname, char *prefix)
+static int processBinaryFile(Package pkg, struct FileList *fl, char *fileName)
+{
+ char fullname[BUFSIZ];
+ glob_t glob_result;
+ int x, offset, rc = 0;
+
+ /* check that file starts with leading "/" */
+ if (*fileName != '/') {
+ rpmError(RPMERR_BADSPEC, "File needs leading \"/\": %s", *fileName);
+ fl->processingFailed = 1;
+ return 1;
+ }
+
+ if (myGlobPatternP(fileName)) {
+ if (fl->buildRoot) {
+ sprintf(fullname, "%s%s", fl->buildRoot, fileName);
+ offset = strlen(fl->buildRoot);
+ } else {
+ strcpy(fullname, fileName);
+ offset = 0;
+ }
+
+ if (glob(fullname, 0, glob_error, &glob_result) ||
+ (glob_result.gl_pathc < 1)) {
+ rpmError(RPMERR_BADSPEC, "File not found: %s", fullname);
+ fl->processingFailed = 1;
+ globfree(&glob_result);
+ return 1;
+ }
+
+ x = 0;
+ while (x < glob_result.gl_pathc) {
+ rc = addFile(fl, &(glob_result.gl_pathv[x][offset]), NULL);
+ x++;
+ }
+ globfree(&glob_result);
+ } else {
+ rc = addFile(fl, fileName, NULL);
+ }
+
+ return rc;
+}
+
+static int addFile(struct FileList *fl, char *name, struct stat *statp)
{
- struct file_entry *p;
- char *copyTo, copied;
- const char *prefixTest, *prefixPtr;
- const char *copyFrom;
- char fullname[1024];
- int mode;
-
- /* Set these up for ftw() */
- Gfestack = festack;
- Gisdoc = isdoc;
- Gconf = conf;
- Gisghost = isghost;
- Gverify_flags = verify_flags;
- GPmode = Pmode;
- GUname = Uname;
- GGname = Gname;
- Gprefix = prefix;
-
- p = malloc(sizeof(struct file_entry));
-
- copyTo = p->file;
+ char fileName[BUFSIZ];
+ char diskName[BUFSIZ];
+ char *copyTo, *copyFrom, copied;
+ char *prefixTest, *prefixPtr;
+ struct stat statbuf;
+ int_16 fileMode;
+ int fileUid, fileGid;
+ char *fileUname, *fileGname;
+
+ /* Copy to fileName, eliminate duplicate "/" and trailing "/" */
+ copyTo = fileName;
copied = '\0';
copyFrom = name;
while (*copyFrom) {
@@ -655,178 +707,325 @@ static int add_file(struct file_entry **festack, const char *name,
copyFrom++;
}
*copyTo = '\0';
+ copyTo--;
+ if ((copyTo != fileName) && (*copyTo == '/')) {
+ *copyTo = '\0';
+ }
- p->isdoc = isdoc;
- p->conf = conf;
- p->isghost = isghost;
- p->isspecfile = 0; /* source packages are done by hand */
- p->verify_flags = verify_flags;
- if (rpmGetVar(RPMVAR_ROOT)) {
- sprintf(fullname, "%s%s", rpmGetVar(RPMVAR_ROOT), name);
+ if (fl->inFtw) {
+ /* Any buildRoot is already prepended */
+ strcpy(diskName, fileName);
+ if (fl->buildRoot) {
+ strcpy(fileName, diskName + strlen(fl->buildRoot));
+ }
} else {
- strcpy(fullname, name);
+ if (fl->buildRoot) {
+ sprintf(diskName, "%s%s", fl->buildRoot, fileName);
+ } else {
+ strcpy(diskName, fileName);
+ }
}
/* If we are using a prefix, validate the file */
- if (prefix) {
- prefixTest = name;
- prefixPtr = prefix;
- while (*prefixTest == '/') {
- prefixTest++; /* Skip leading "/" */
- }
+ if (!fl->inFtw && fl->prefix) {
+ prefixTest = fileName;
+ prefixPtr = fl->prefix;
+
while (*prefixPtr && *prefixTest && (*prefixTest == *prefixPtr)) {
prefixPtr++;
prefixTest++;
}
- if (*prefixPtr) {
+ if (*prefixPtr || (*prefixTest && *prefixTest != '/')) {
rpmError(RPMERR_BADSPEC, "File doesn't match prefix (%s): %s",
- prefix, name);
- return 0;
+ fl->prefix, fileName);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
}
- /* OK, finally stat() the file */
- if (lstat(fullname, &p->statbuf)) {
- return 0;
- }
-
- /*
- * If %attr() was specified, then use those values instead of
- * what lstat() returned.
- */
- if (Pmode && strcmp(Pmode, "-")) {
- sscanf(Pmode, "%o", &mode);
- mode |= p->statbuf.st_mode & S_IFMT;
- p->statbuf.st_mode = (unsigned short)mode;
+ if (! statp) {
+ statp = &statbuf;
+ if (lstat(diskName, statp)) {
+ rpmError(RPMERR_BADSPEC, "File not found: %s", diskName);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
}
- if (Uname && strcmp(Uname, "-")) {
- p->uname = getUnameS(Uname);
- } else {
- p->uname = getUname(p->statbuf.st_uid);
- }
-
- if (Gname && strcmp(Gname, "-")) {
- p->gname = getGnameS(Gname);
- } else {
- p->gname = getGname(p->statbuf.st_gid);
- }
-
- if (! (p->uname && p->gname)) {
- rpmError(RPMERR_BADSPEC, "Bad owner/group: %s\n", fullname);
- p->uname = "";
- p->gname = "";
- return 0;
- }
-
- if ((! isdir) && S_ISDIR(p->statbuf.st_mode)) {
- /* This means we need to descend with ftw() */
- Gcount = 0;
-
+ if ((! fl->isDir) && S_ISDIR(statp->st_mode)) {
/* We use our own ftw() call, because ftw() uses stat() */
/* instead of lstat(), which causes it to follow symlinks! */
- myftw(fullname, add_file_aux, 16);
+ /* It also has better callback support. */
- free(p);
-
- return Gcount;
+ fl->inFtw = 1; /* Flag to indicate file has buildRoot prefixed */
+ fl->isDir = 1; /* Keep it from following myftw() again */
+ myftw(diskName, 16, addFile, fl);
+ fl->isDir = 0;
+ fl->inFtw = 0;
} else {
- /* Link it in */
- p->next = *festack;
- *festack = p;
+ fileMode = statp->st_mode;
+ fileUid = statp->st_uid;
+ fileGid = statp->st_gid;
+
+ /* %attr ? */
+ if (S_ISDIR(fileMode) && fl->current.PdirmodeString) {
+ if (fl->current.PdirmodeString[0] != '-') {
+ fileMode &= S_IFMT;
+ fileMode |= fl->current.Pdirmode;
+ }
+ } else {
+ if (fl->current.PmodeString) {
+ fileMode &= S_IFMT;
+ fileMode |= fl->current.Pmode;
+ }
+ }
+ if (fl->current.Uname) {
+ fileUname = getUnameS(fl->current.Uname);
+ } else {
+ fileUname = getUname(fileUid);
+ }
+ if (fl->current.Gname) {
+ fileGname = getGnameS(fl->current.Gname);
+ } else {
+ fileGname = getGname(fileGid);
+ }
+
+ if (! (fileUname && fileGname)) {
+ rpmError(RPMERR_BADSPEC, "Bad owner/group: %s\n", diskName);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
+
+ rpmMessage(RPMMESS_DEBUG, "File %d: %s\n", fl->fileCount, fileName);
+
+ /* Add to the file list */
+ if (fl->fileListRecsUsed == fl->fileListRecsAlloced) {
+ fl->fileListRecsAlloced += 128;
+ fl->fileList = realloc(fl->fileList,
+ fl->fileListRecsAlloced *
+ sizeof(*(fl->fileList)));
+ }
+
+ fl->fileList[fl->fileListRecsUsed].fileName = strdup(fileName);
+ fl->fileList[fl->fileListRecsUsed].diskName = strdup(diskName);
+ fl->fileList[fl->fileListRecsUsed].mode = fileMode;
+ fl->fileList[fl->fileListRecsUsed].uid = fileUid;
+ fl->fileList[fl->fileListRecsUsed].gid = fileGid;
+ fl->fileList[fl->fileListRecsUsed].uname = fileUname;
+ fl->fileList[fl->fileListRecsUsed].gname = fileGname;
+
+ fl->fileList[fl->fileListRecsUsed].lang =
+ strdup(fl->currentLang ? fl->currentLang : "");
+
+ fl->fileList[fl->fileListRecsUsed].flags = fl->currentFlags;
+ fl->fileList[fl->fileListRecsUsed].verifyFlags =
+ fl->currentVerifyFlags;
+ fl->fileList[fl->fileListRecsUsed].size = statp->st_size;
+ fl->fileList[fl->fileListRecsUsed].mtime = statp->st_mtime;
+ fl->fileList[fl->fileListRecsUsed].rdev = statp->st_rdev;
+ fl->fileList[fl->fileListRecsUsed].device = statp->st_dev;
+ fl->fileList[fl->fileListRecsUsed].inode = statp->st_ino;
+ fl->fileListRecsUsed++;
+
+ fl->totalFileSize += statp->st_size;
+ fl->fileCount++;
+ }
- rpmMessage(RPMMESS_DEBUG, "ADDING: %s\n", name);
+ return 0;
+}
- /* return number of entries added */
- return 1;
+static int parseForSimple(Spec spec, Package pkg, char *buf,
+ struct FileList *fl, char **fileName)
+{
+ char *s;
+ int res, specialDoc = 0;
+ char *name, *version;
+ char specialDocBuf[BUFSIZ];
+
+ specialDocBuf[0] = '\0';
+ *fileName = NULL;
+ res = 0;
+ s = strtok(buf, " \t\n");
+ while (s) {
+ if (!strcmp(s, "%docdir")) {
+ s = strtok(NULL, " \t\n");
+ if (fl->docDirCount == MAXDOCDIR) {
+ rpmError(RPMERR_INTERNAL, "Hit limit for %%docdir");
+ fl->processingFailed = 1;
+ res = 1;
+ }
+ fl->docDirs[fl->docDirCount++] = strdup(s);
+ if (strtok(NULL, " \t\n")) {
+ rpmError(RPMERR_INTERNAL, "Only one arg for %%docdir");
+ fl->processingFailed = 1;
+ res = 1;
+ }
+ break;
+ } else if (!strcmp(s, "%doc")) {
+ fl->currentFlags |= RPMFILE_DOC;
+ } else if (!strcmp(s, "%ghost")) {
+ fl->currentFlags |= RPMFILE_GHOST;
+ } else if (!strcmp(s, "%dir")) {
+ fl->isDir = 1;
+ } else {
+ if (*fileName) {
+ /* We already got a file -- error */
+ rpmError(RPMERR_BADSPEC,
+ "Two files on one line: %s", *fileName);
+ fl->processingFailed = 1;
+ res = 1;
+ }
+ if (*s != '/') {
+ if (fl->currentFlags & RPMFILE_DOC) {
+ specialDoc = 1;
+ strcat(specialDocBuf, " ");
+ strcat(specialDocBuf, s);
+ } else {
+ /* not in %doc, does not begin with / -- error */
+ rpmError(RPMERR_BADSPEC,
+ "File must begin with \"/\": %s", s);
+ fl->processingFailed = 1;
+ res = 1;
+ }
+ } else {
+ *fileName = s;
+ }
+ }
+ s = strtok(NULL, " \t\n");
+ }
+
+ if (specialDoc) {
+ if (*fileName || (fl->currentFlags & ~(RPMFILE_DOC))) {
+ rpmError(RPMERR_BADSPEC,
+ "Can't mix special %%doc with other forms: %s",
+ *fileName);
+ fl->processingFailed = 1;
+ res = 1;
+ } else {
+ headerGetEntry(pkg->header, RPMTAG_NAME, NULL,
+ (void *) &name, NULL);
+ headerGetEntry(pkg->header, RPMTAG_VERSION, NULL,
+ (void *) &version, NULL);
+ sprintf(buf, "%s/%s-%s", spec->docDir, name, version);
+
+ if (! fl->passedSpecialDoc) {
+ pkg->specialDoc = newStringBuf();
+ appendStringBuf(pkg->specialDoc,
+ "export DOCDIR=$RPM_BUILD_ROOT");
+ appendLineStringBuf(pkg->specialDoc, buf);
+ appendLineStringBuf(pkg->specialDoc, "rm -rf $DOCDIR");
+ appendLineStringBuf(pkg->specialDoc, "mkdir -p $DOCDIR");
+
+ *fileName = buf;
+ fl->passedSpecialDoc = 1;
+ fl->isSpecialDoc = 1;
+ }
+
+ appendStringBuf(pkg->specialDoc, "cp -pr ");
+ appendStringBuf(pkg->specialDoc, specialDocBuf);
+ appendLineStringBuf(pkg->specialDoc, " $DOCDIR");
+ }
}
+
+ return res;
}
-static int add_file_aux(const char *file, struct stat *sb, int flag)
+static int parseForVerify(char *buf, struct FileList *fl)
{
- const char *name = file;
+ char *p, *start, *end, *name;
+ char ourbuf[BUFSIZ];
+ int not, verifyFlags;
+ int *resultVerify;
- if (rpmGetVar(RPMVAR_ROOT)) {
- name += strlen(rpmGetVar(RPMVAR_ROOT));
+ if (!(p = start = strstr(buf, "%verify"))) {
+ if (!(p = start = strstr(buf, "%defverify"))) {
+ return 0;
+ }
+ name = "%defverify";
+ resultVerify = &(fl->defVerifyFlags);
+ p += 10;
+ } else {
+ name = "%verify";
+ resultVerify = &(fl->currentVerifyFlags);
+ p += 7;
}
- /* The 1 will cause add_file() to *not* descend */
- /* directories -- ftw() is already doing it! */
- Gcount += add_file(Gfestack, name, Gisdoc, Gconf, 1, Gisghost,
- Gverify_flags,
- GPmode, GUname, GGname, Gprefix);
+ SKIPSPACE(p);
- return 0; /* for ftw() */
-}
+ if (*p != '(') {
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
+ p++;
-/*************************************************************/
-/* */
-/* globbing */
-/* */
-/*************************************************************/
+ end = p;
+ while (*end && *end != ')') {
+ end++;
+ }
-/* glob_pattern_p() taken from bash
- * Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
- */
+ if (! *end) {
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
-/* Return nonzero if PATTERN has any special globbing chars in it. */
-static int glob_pattern_p (char *pattern)
-{
- register char *p = pattern;
- register char c;
- int open = 0;
-
- while ((c = *p++) != '\0')
- switch (c) {
- case '?':
- case '*':
- return (1);
- case '[': /* Only accept an open brace if there is a close */
- open++; /* brace to match it. Bracket expressions must be */
- continue; /* complete, according to Posix.2 */
- case ']':
- if (open)
- return (1);
- continue;
- case '\\':
- if (*p++ == '\0')
- return (0);
+ strncpy(ourbuf, p, end-p);
+ ourbuf[end-p] = '\0';
+ while (start <= end) {
+ *start++ = ' ';
+ }
+
+ p = strtok(ourbuf, ", \n\t");
+ not = 0;
+ verifyFlags = RPMVERIFY_NONE;
+ while (p) {
+ if (!strcmp(p, "not")) {
+ not = 1;
+ } else if (!strcmp(p, "md5")) {
+ verifyFlags |= RPMVERIFY_MD5;
+ } else if (!strcmp(p, "size")) {
+ verifyFlags |= RPMVERIFY_FILESIZE;
+ } else if (!strcmp(p, "link")) {
+ verifyFlags |= RPMVERIFY_LINKTO;
+ } else if (!strcmp(p, "user")) {
+ verifyFlags |= RPMVERIFY_USER;
+ } else if (!strcmp(p, "group")) {
+ verifyFlags |= RPMVERIFY_GROUP;
+ } else if (!strcmp(p, "mtime")) {
+ verifyFlags |= RPMVERIFY_MTIME;
+ } else if (!strcmp(p, "mode")) {
+ verifyFlags |= RPMVERIFY_MODE;
+ } else if (!strcmp(p, "rdev")) {
+ verifyFlags |= RPMVERIFY_RDEV;
+ } else {
+ rpmError(RPMERR_BADSPEC, "Invalid %s token: %s", name, p);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
+ p = strtok(NULL, ", \n\t");
+ }
- return (0);
-}
+ *resultVerify = not ? ~(verifyFlags) : verifyFlags;
-static int glob_error(const char *foo, int bar)
-{
- return 1;
+ return 0;
}
-/*************************************************************/
-/* */
-/* %attr parsing */
-/* */
-/*************************************************************/
-
-static int parseForAttr(char *buf, char **currPmode,
- char **currUname, char **currGname)
+static int parseForLang(char *buf, struct FileList *fl)
{
char *p, *start, *end;
char ourbuf[1024];
- int mode, x;
- if (!(p = start = strstr(buf, "%attr"))) {
+ if (!(p = start = strstr(buf, "%lang"))) {
return 0;
}
- *currPmode = *currUname = *currGname = NULL;
-
p += 5;
- while (*p && (*p == ' ' || *p == '\t')) {
- p++;
- }
+ SKIPSPACE(p);
if (*p != '(') {
- rpmError(RPMERR_BADSPEC, "Bad %%attr() syntax: %s", buf);
+ rpmError(RPMERR_BADSPEC, "Bad %%lang() syntax: %s", buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
p++;
@@ -837,68 +1036,66 @@ static int parseForAttr(char *buf, char **currPmode,
}
if (! *end) {
- rpmError(RPMERR_BADSPEC, "Bad %%attr() syntax: %s", buf);
+ rpmError(RPMERR_BADSPEC, "Bad %%lang() syntax: %s", buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
strncpy(ourbuf, p, end-p);
ourbuf[end-p] = '\0';
+ while (start <= end) {
+ *start++ = ' ';
+ }
- *currPmode = strtok(ourbuf, ", \n\t");
- *currUname = strtok(NULL, ", \n\t");
- *currGname = strtok(NULL, ", \n\t");
-
- if (! (*currPmode && *currUname && *currGname)) {
- rpmError(RPMERR_BADSPEC, "Bad %%attr() syntax: %s", buf);
- *currPmode = *currUname = *currGname = NULL;
+ p = strtok(ourbuf, ", \n\t");
+ if (!p) {
+ rpmError(RPMERR_BADSPEC, "Bad %%lang() syntax: %s", buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
-
- /* Do a quick test on the mode argument */
- if (strcmp(*currPmode, "-")) {
- x = sscanf(*currPmode, "%o", &mode);
- if ((x == 0) || (mode >> 12)) {
- rpmError(RPMERR_BADSPEC, "Bad %%attr() mode spec: %s", buf);
- *currPmode = *currUname = *currGname = NULL;
- return RPMERR_BADSPEC;
- }
+ if (strlen(p) != 2) {
+ rpmError(RPMERR_BADSPEC, "%%lang() entries are 2 characters: %s", buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
-
- *currPmode = strdup(*currPmode);
- *currUname = strdup(*currUname);
- *currGname = strdup(*currGname);
-
- /* Set everything we just parsed to blank spaces */
- while (start <= end) {
- *start++ = ' ';
+ if (strtok(NULL, ", \n\t")) {
+ rpmError(RPMERR_BADSPEC, "Only one entry in %%lang(): %s", buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
-
+ fl->currentLang = strdup(p);
+
return 0;
}
-/*************************************************************/
-/* */
-/* %verify parsing */
-/* */
-/*************************************************************/
-
-static int parseForVerify(char *buf, int *verify_flags)
+static int parseForAttr(char *buf, struct FileList *fl)
{
- char *p, *start, *end;
+ char *p, *s, *start, *end, *name;
char ourbuf[1024];
- int not;
+ int x, defattr = 0;
+ struct AttrRec *resultAttr;
- if (!(p = start = strstr(buf, "%verify"))) {
- return 0;
+ if (!(p = start = strstr(buf, "%attr"))) {
+ if (!(p = start = strstr(buf, "%defattr"))) {
+ return 0;
+ }
+ defattr = 1;
+ name = "%defattr";
+ resultAttr = &(fl->def);
+ p += 8;
+ } else {
+ name = "%attr";
+ resultAttr = &(fl->current);
+ p += 5;
}
- p += 7;
- while (*p && (*p == ' ' || *p == '\t')) {
- p++;
- }
+ resultAttr->PmodeString = resultAttr->Uname = resultAttr->Gname = NULL;
+
+ SKIPSPACE(p);
if (*p != '(') {
- rpmError(RPMERR_BADSPEC, "Bad %%verify() syntax: %s", buf);
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
p++;
@@ -909,53 +1106,92 @@ static int parseForVerify(char *buf, int *verify_flags)
}
if (! *end) {
- rpmError(RPMERR_BADSPEC, "Bad %%verify() syntax: %s", buf);
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
+ if (defattr) {
+ s = end;
+ s++;
+ SKIPSPACE(s);
+ if (*s) {
+ rpmError(RPMERR_BADSPEC,
+ "No files after %%defattr(): %s", buf);
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
+ }
+
strncpy(ourbuf, p, end-p);
ourbuf[end-p] = '\0';
- while (start <= end) {
- *start++ = ' ';
+
+ resultAttr->PmodeString = strtok(ourbuf, ", \n\t");
+ resultAttr->Uname = strtok(NULL, ", \n\t");
+ resultAttr->Gname = strtok(NULL, ", \n\t");
+ resultAttr->PdirmodeString = strtok(NULL, ", \n\t");
+
+ if (! (resultAttr->PmodeString &&
+ resultAttr->Uname && resultAttr->Gname)) {
+ rpmError(RPMERR_BADSPEC, "Bad %s() syntax: %s", name, buf);
+ resultAttr->PmodeString = resultAttr->Uname = resultAttr->Gname = NULL;
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
}
- p = strtok(ourbuf, ", \n\t");
- not = 0;
- *verify_flags = RPMVERIFY_NONE;
- while (p) {
- if (!strcmp(p, "not")) {
- not = 1;
- } else if (!strcmp(p, "md5")) {
- *verify_flags |= RPMVERIFY_MD5;
- } else if (!strcmp(p, "size")) {
- *verify_flags |= RPMVERIFY_FILESIZE;
- } else if (!strcmp(p, "link")) {
- *verify_flags |= RPMVERIFY_LINKTO;
- } else if (!strcmp(p, "user")) {
- *verify_flags |= RPMVERIFY_USER;
- } else if (!strcmp(p, "group")) {
- *verify_flags |= RPMVERIFY_GROUP;
- } else if (!strcmp(p, "mtime")) {
- *verify_flags |= RPMVERIFY_MTIME;
- } else if (!strcmp(p, "mode")) {
- *verify_flags |= RPMVERIFY_MODE;
- } else if (!strcmp(p, "rdev")) {
- *verify_flags |= RPMVERIFY_RDEV;
- } else {
- rpmError(RPMERR_BADSPEC, "Invalid %%verify token: %s", p);
+ /* Do a quick test on the mode argument and adjust for "-" */
+ if (!strcmp(resultAttr->PmodeString, "-")) {
+ resultAttr->PmodeString = NULL;
+ } else {
+ x = sscanf(resultAttr->PmodeString, "%o", &(resultAttr->Pmode));
+ if ((x == 0) || (resultAttr->Pmode >> 12)) {
+ rpmError(RPMERR_BADSPEC, "Bad %s() mode spec: %s", name, buf);
+ resultAttr->PmodeString = resultAttr->Uname =
+ resultAttr->Gname = NULL;
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
- p = strtok(NULL, ", \n\t");
+ resultAttr->PmodeString = strdup(resultAttr->PmodeString);
}
-
- if (not) {
- *verify_flags = ~(*verify_flags);
+ if (resultAttr->PdirmodeString) {
+ /* The processing here is slightly different to maintain */
+ /* compatibility with old spec files. */
+ if (!strcmp(resultAttr->PdirmodeString, "-")) {
+ resultAttr->PdirmodeString = strdup(resultAttr->PdirmodeString);
+ } else {
+ x = sscanf(resultAttr->PdirmodeString, "%o",
+ &(resultAttr->Pdirmode));
+ if ((x == 0) || (resultAttr->Pdirmode >> 12)) {
+ rpmError(RPMERR_BADSPEC,
+ "Bad %s() dirmode spec: %s", name, buf);
+ resultAttr->PmodeString = resultAttr->Uname =
+ resultAttr->Gname = resultAttr->PdirmodeString = NULL;
+ fl->processingFailed = 1;
+ return RPMERR_BADSPEC;
+ }
+ resultAttr->PdirmodeString = strdup(resultAttr->PdirmodeString);
+ }
+ }
+ if (!strcmp(resultAttr->Uname, "-")) {
+ resultAttr->Uname = NULL;
+ } else {
+ resultAttr->Uname = strdup(resultAttr->Uname);
+ }
+ if (!strcmp(resultAttr->Gname, "-")) {
+ resultAttr->Gname = NULL;
+ } else {
+ resultAttr->Gname = strdup(resultAttr->Gname);
+ }
+
+ /* Set everything we just parsed to blank spaces */
+ while (start <= end) {
+ *start++ = ' ';
}
return 0;
}
-static int parseForConfig(char *buf, int *conf)
+static int parseForConfig(char *buf, struct FileList *fl)
{
char *p, *start, *end;
char ourbuf[1024];
@@ -963,12 +1199,10 @@ static int parseForConfig(char *buf, int *conf)
if (!(p = start = strstr(buf, "%config"))) {
return 0;
}
- *conf = RPMFILE_CONFIG;
+ fl->currentFlags = RPMFILE_CONFIG;
p += 7;
- while (*p && (*p == ' ' || *p == '\t')) {
- p++;
- }
+ SKIPSPACE(p);
if (*p != '(') {
while (start < p) {
@@ -985,6 +1219,7 @@ static int parseForConfig(char *buf, int *conf)
if (! *end) {
rpmError(RPMERR_BADSPEC, "Bad %%config() syntax: %s", buf);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
@@ -997,11 +1232,12 @@ static int parseForConfig(char *buf, int *conf)
p = strtok(ourbuf, ", \n\t");
while (p) {
if (!strcmp(p, "missingok")) {
- *conf |= RPMFILE_MISSINGOK;
+ fl->currentFlags |= RPMFILE_MISSINGOK;
} else if (!strcmp(p, "noreplace")) {
- *conf |= RPMFILE_NOREPLACE;
+ fl->currentFlags |= RPMFILE_NOREPLACE;
} else {
rpmError(RPMERR_BADSPEC, "Invalid %%config token: %s", p);
+ fl->processingFailed = 1;
return RPMERR_BADSPEC;
}
p = strtok(NULL, ", \n\t");
@@ -1009,3 +1245,39 @@ static int parseForConfig(char *buf, int *conf)
return 0;
}
+
+/* glob_pattern_p() taken from bash
+ * Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
+ *
+ * Return nonzero if PATTERN has any special globbing chars in it.
+ */
+static int myGlobPatternP (char *pattern)
+{
+ register char *p = pattern;
+ register char c;
+ int open = 0;
+
+ while ((c = *p++) != '\0')
+ switch (c) {
+ case '?':
+ case '*':
+ return (1);
+ case '[': /* Only accept an open brace if there is a close */
+ open++; /* brace to match it. Bracket expressions must be */
+ continue; /* complete, according to Posix.2 */
+ case ']':
+ if (open)
+ return (1);
+ continue;
+ case '\\':
+ if (*p++ == '\0')
+ return (0);
+ }
+
+ return (0);
+}
+
+static int glob_error(const char *foo, int bar)
+{
+ return 1;
+}
diff --git a/build/files.h b/build/files.h
index 235e05a82..61239e2ea 100644
--- a/build/files.h
+++ b/build/files.h
@@ -1,14 +1,8 @@
-#ifndef _FILES_H_
-#define _FILES_H_
-
#include "spec.h"
-#include "specP.h"
-#include "stringbuf.h"
-
-int finish_filelists(Spec spec);
+#include "package.h"
+#include "lib/cpio.h"
-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);
diff --git a/build/macro.c b/build/macro.c
index 19a4fd878..17319161c 100644
--- a/build/macro.c
+++ b/build/macro.c
@@ -4,48 +4,42 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+
#include "macro.h"
+#include "misc.h"
-#ifdef DEBUG
+#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,106 +196,115 @@ static int handleDefine(char *buf)
}
}
- expandMacros(expansion);
- addMacro(name, expansion);
+ expandMacros(mc, expansion);
+ addMacro(mc, name, expansion);
return 0;
}
-#ifdef DEBUG
-static void dumpTable()
-{
- int i;
-
- for (i = 0; i < firstFree; i++) {
- printf("%s->%s.\n", macroTable[i].name,
- macroTable[i].expansion);
- }
-}
-
-void main(void)
-{
- char buf[1024];
- int x;
-
- while(gets(buf)) {
- x = expandMacros(buf);
- printf("%d->%s<-\n", x, buf);
- }
-}
-#endif
-
/*************************************************************************/
/* */
/* Table handling routines */
/* */
/*************************************************************************/
-void resetMacros(void)
+void initMacros(struct MacroContext *mc)
+{
+ mc->macrosAllocated = 0;
+ mc->firstFree = 0;
+ mc->macroTable = NULL;
+ expandMacroTable(mc);
+
+}
+
+void freeMacros(struct MacroContext *mc)
{
int i;
- if (! macrosAllocated) {
- expandMacroTable();
- return;
- }
-
- for (i = 0; i < firstFree; i++) {
- free(macroTable[i].name);
- free(macroTable[i].expansion);
+ for (i = 0; i < mc->firstFree; i++) {
+ FREE(mc->macroTable[i].name);
+ FREE(mc->macroTable[i].expansion);
}
- firstFree = 0;
+ FREE(mc->macroTable);
}
-void addMacro(char *name, char *expansion)
+void addMacro(struct MacroContext *mc, char *name, char *expansion)
{
- struct macroEntry *p;
+ struct MacroEntry *p;
- p = findEntry(name);
+ p = findEntry(mc, name);
if (p) {
free(p->expansion);
p->expansion = strdup(expansion);
return;
}
- if (firstFree == macrosAllocated) {
- expandMacroTable();
+ if (mc->firstFree == mc->macrosAllocated) {
+ expandMacroTable(mc);
}
- p = macroTable + firstFree++;
+ p = mc->macroTable + mc->firstFree++;
p->name = strdup(name);
p->expansion = strdup(expansion);
- qsort(macroTable, firstFree, sizeof(*macroTable), compareMacros);
+ qsort(mc->macroTable, mc->firstFree, sizeof(*(mc->macroTable)),
+ compareMacros);
}
-static struct macroEntry *findEntry(char *name)
+static struct MacroEntry *findEntry(struct MacroContext *mc, char *name)
{
- struct macroEntry key;
+ struct MacroEntry key;
- if (! firstFree) {
+ if (! mc->firstFree) {
return NULL;
}
key.name = name;
- return bsearch(&key, macroTable, firstFree,
- sizeof(*macroTable), compareMacros);
+ 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);
+ return strcmp(((struct MacroEntry *)ap)->name,
+ ((struct MacroEntry *)bp)->name);
}
-static void expandMacroTable()
+static void expandMacroTable(struct MacroContext *mc)
{
- macrosAllocated += MACRO_CHUNK_SIZE;
- if (! macrosAllocated) {
- macroTable = malloc(sizeof(*macroTable) * macrosAllocated);
- firstFree = 0;
+ mc->macrosAllocated += MACRO_CHUNK_SIZE;
+ if (! mc->macrosAllocated) {
+ mc->macroTable = malloc(sizeof(*(mc->macroTable)) *
+ mc->macrosAllocated);
+ mc->firstFree = 0;
} else {
- macroTable = realloc(macroTable,
- sizeof(*macroTable) * macrosAllocated);
+ mc->macroTable = realloc(mc->macroTable, sizeof(*(mc->macroTable)) *
+ mc->macrosAllocated);
+ }
+}
+
+/***********************************************************************/
+
+#ifdef DEBUG_MACROS
+static void dumpTable()
+{
+ int i;
+
+ for (i = 0; i < firstFree; i++) {
+ printf("%s->%s.\n", macroTable[i].name,
+ macroTable[i].expansion);
+ }
+}
+
+void main(void)
+{
+ char buf[1024];
+ int x;
+
+ while(gets(buf)) {
+ x = expandMacros(buf);
+ printf("%d->%s<-\n", x, buf);
}
}
+#endif
+
diff --git a/build/macro.h b/build/macro.h
index ad9b35277..8d3b8d0d2 100644
--- a/build/macro.h
+++ b/build/macro.h
@@ -1,8 +1,25 @@
+#ifndef _MACRO_H_
+#define _MACRO_H_
+
/* macro.h - %macro handling */
-void resetMacros(void);
+struct MacroEntry {
+ char *name;
+ char *expansion;
+};
+
+struct MacroContext {
+ struct MacroEntry *macroTable;
+ int macrosAllocated;
+ int firstFree;
+};
-void addMacro(char *name, char *expansion);
+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
diff --git a/build/misc.c b/build/misc.c
new file mode 100644
index 000000000..7437f3d2a
--- /dev/null
+++ b/build/misc.c
@@ -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;
+}
diff --git a/build/misc.h b/build/misc.h
new file mode 100644
index 000000000..1ac941509
--- /dev/null
+++ b/build/misc.h
@@ -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
diff --git a/build/myftw.c b/build/myftw.c
index 28173b5b3..c7a69e8a0 100644
--- a/build/myftw.c
+++ b/build/myftw.c
@@ -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;
diff --git a/build/myftw.h b/build/myftw.h
index fd82d7609..05bec77ed 100644
--- a/build/myftw.h
+++ b/build/myftw.h
@@ -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_
diff --git a/build/names.c b/build/names.c
index 77cb8fe30..c619c692c 100644
--- a/build/names.c
+++ b/build/names.c
@@ -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)
diff --git a/build/names.h b/build/names.h
index 4e797448f..d23adca31 100644
--- a/build/names.h
+++ b/build/names.h
@@ -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_
diff --git a/build/pack.c b/build/pack.c
index 0320246ca..ad149dccf 100644
--- a/build/pack.c
+++ b/build/pack.c
@@ -1,243 +1,290 @@
-/* The very final packaging steps */
-
-#include "config.h"
-#include "miscfn.h"
-
-#if HAVE_ALLOCA_H
-# include <alloca.h>
-#endif
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/wait.h>
-#include <signal.h>
#include <fcntl.h>
+#include <malloc.h>
#include <string.h>
#include <errno.h>
+#include <signal.h>
+#include <time.h>
-#include <sys/time.h> /* For 'select()' interfaces */
-
-#include "cpio.h"
-#include "pack.h"
-#include "header.h"
#include "spec.h"
-#include "specP.h"
-#include "signature.h"
-#include "rpmlead.h"
-#include "rpmlib.h"
+#include "header.h"
#include "misc.h"
-#include "stringbuf.h"
+#include "reqprov.h"
#include "names.h"
+#include "macro.h"
+
+#include "rpmlib.h"
#include "files.h"
-#include "reqprov.h"
-#include "trigger.h"
-#include "messages.h"
-
-static int writeMagic(int fd, char *name, unsigned short type);
-static int cpio_gzip(int fd, char *tempdir, char *writePtr,
- int *archiveSize, char *prefix);
-static int generateRPM(char *name, /* name-version-release */
- char *filename, /* output filename */
- int type, /* source or binary */
- Header header, /* the header */
- char *stempdir, /* directory containing sources */
- char *fileList, /* list of files for cpio */
- char *passPhrase, /* PGP passphrase */
- char *prefix);
-
-
-static int generateRPM(char *name, /* name-version-release */
- char *filename, /* output filename */
- int type, /* source or binary */
- Header header, /* the header */
- char *stempdir, /* directory containing sources */
- char *fileList, /* list of files for cpio */
- char *passPhrase,
- char *prefix)
+#include "lib/cpio.h"
+#include "lib/misc.h"
+#include "lib/signature.h"
+#include "lib/rpmlead.h"
+#include "lib/messages.h"
+
+#define RPM_MAJOR_NUMBER 3
+
+static int processScriptFiles(Spec spec, Package pkg);
+static int addFileToTag(Spec spec, char *file, Header h, int tag);
+static int writeRPM(Header header, char *fileName, int type,
+ struct cpioFileMapping *cpioList, int cpioCount,
+ char *passPhrase, char **cookie);
+static int cpio_gzip(int fd, struct cpioFileMapping *cpioList,
+ int cpioCount, int *archiveSize);
+
+int packageSources(Spec spec)
+{
+ char *name, *version, *release;
+ char fileName[BUFSIZ];
+ HeaderIterator iter;
+ int_32 tag, count;
+ char **ptr;
+
+ /* Add some cruft */
+ headerAddEntry(spec->sourceHeader, RPMTAG_RPMVERSION,
+ RPM_STRING_TYPE, VERSION, 1);
+ headerAddEntry(spec->sourceHeader, RPMTAG_BUILDHOST,
+ RPM_STRING_TYPE, buildHost(), 1);
+ headerAddEntry(spec->sourceHeader, RPMTAG_BUILDTIME,
+ RPM_INT32_TYPE, getBuildTime(), 1);
+
+ headerGetEntry(spec->sourceHeader, RPMTAG_NAME,
+ NULL, (void **)&name, NULL);
+ headerGetEntry(spec->sourceHeader, RPMTAG_VERSION,
+ NULL, (void **)&version, NULL);
+ headerGetEntry(spec->sourceHeader, RPMTAG_RELEASE,
+ NULL, (void **)&release, NULL);
+ sprintf(fileName, "%s-%s-%s.%ssrc.rpm", name, version, release,
+ spec->noSource ? "no" : "");
+ spec->sourceRpmName = strdup(fileName);
+ sprintf(fileName, "%s/%s", rpmGetVar(RPMVAR_SRPMDIR), spec->sourceRpmName);
+
+ /* Add the build restrictions */
+ iter = headerInitIterator(spec->buildRestrictions);
+ while (headerNextIterator(iter, &tag, NULL, (void **)&ptr, &count)) {
+ headerAddEntry(spec->sourceHeader, tag,
+ RPM_STRING_ARRAY_TYPE, ptr, count);
+ FREE(ptr);
+ }
+ headerFreeIterator(iter);
+ if (spec->buildArchitectureCount) {
+ headerAddEntry(spec->sourceHeader, RPMTAG_BUILDARCHS,
+ RPM_STRING_ARRAY_TYPE,
+ spec->buildArchitectures, spec->buildArchitectureCount);
+ }
+
+ FREE(spec->cookie);
+
+ return writeRPM(spec->sourceHeader, fileName, RPMLEAD_SOURCE,
+ spec->sourceCpioList, spec->sourceCpioCount,
+ spec->passPhrase, &(spec->cookie));
+}
+
+int packageBinaries(Spec spec)
+{
+ int rc;
+ char *binFormat, *binRpm, *errorString;
+ char *name, fileName[BUFSIZ];
+ Package pkg;
+
+ pkg = spec->packages;
+ while (pkg) {
+ if (!pkg->fileList) {
+ pkg = pkg->next;
+ continue;
+ }
+
+ if ((rc = processScriptFiles(spec, pkg))) {
+ return rc;
+ }
+
+ generateAutoReqProv(spec, pkg, pkg->cpioList, pkg->cpioCount);
+ printReqs(spec, pkg);
+
+ if (spec->cookie) {
+ headerAddEntry(pkg->header, RPMTAG_COOKIE,
+ RPM_STRING_TYPE, spec->cookie, 1);
+ }
+
+ headerAddEntry(pkg->header, RPMTAG_RPMVERSION,
+ RPM_STRING_TYPE, VERSION, 1);
+ headerAddEntry(pkg->header, RPMTAG_BUILDHOST,
+ RPM_STRING_TYPE, buildHost(), 1);
+ headerAddEntry(pkg->header, RPMTAG_BUILDTIME,
+ RPM_INT32_TYPE, getBuildTime(), 1);
+ headerAddEntry(pkg->header, RPMTAG_SOURCERPM, RPM_STRING_TYPE,
+ spec->sourceRpmName ?
+ spec->sourceRpmName : "(unknown)", 1);
+
+ binFormat = rpmGetVar(RPMVAR_RPMFILENAME);
+ binRpm = headerSprintf(pkg->header, binFormat, rpmTagTable,
+ rpmHeaderFormats, &errorString);
+ if (!binRpm) {
+ headerGetEntry(pkg->header, RPMTAG_NAME, NULL,
+ (void **)&name, NULL);
+ rpmError(RPMERR_BADFILENAME, "Could not generate output "
+ "filename for package %s: %s\n", name, errorString);
+ return RPMERR_BADFILENAME;
+ }
+ sprintf(fileName, "%s/%s", rpmGetVar(RPMVAR_RPMDIR), binRpm);
+ FREE(binRpm);
+
+ if ((rc = writeRPM(pkg->header, fileName, RPMLEAD_BINARY,
+ pkg->cpioList, pkg->cpioCount,
+ spec->passPhrase, NULL))) {
+ return rc;
+ }
+
+ pkg = pkg->next;
+ }
+
+ return 0;
+}
+
+static int writeRPM(Header header, char *fileName, int type,
+ struct cpioFileMapping *cpioList, int cpioCount,
+ char *passPhrase, char **cookie)
{
- int_32 sigtype;
- char *sigtarget;
- int fd, ifd, count, archiveSize;
- unsigned char buffer[8192];
+ int archiveSize, fd, ifd, rc, count, arch, os, sigtype;
+ char *sigtarget, *name, *version, *release;
+ char buf[BUFSIZ];
Header sig;
+ struct rpmlead lead;
/* Add the a bogus archive size to the Header */
headerAddEntry(header, RPMTAG_ARCHIVESIZE, RPM_INT32_TYPE,
&archiveSize, 1);
+ /* Create and add the cookie */
+ if (cookie) {
+ sprintf(buf, "%s %d", buildHost(), (int) time(NULL));
+ *cookie = strdup(buf);
+ headerAddEntry(header, RPMTAG_COOKIE, RPM_STRING_TYPE, *cookie, 1);
+ }
+
/* Write the header */
- if (makeTempFile(NULL, &sigtarget, &fd))
- return 1;
-
+ if (makeTempFile(NULL, &sigtarget, &fd)) {
+ rpmError(RPMERR_CREATE, "Unable to open temp file");
+ return RPMERR_CREATE;
+ }
headerWrite(fd, header, HEADER_MAGIC_YES);
-
+
/* Write the archive and get the size */
- if (cpio_gzip(fd, stempdir, fileList, &archiveSize, prefix)) {
+ if ((rc = cpio_gzip(fd, cpioList, cpioCount, &archiveSize))) {
close(fd);
unlink(sigtarget);
free(sigtarget);
- return 1;
+ return rc;
}
/* Now set the real archive size in the Header */
headerModifyEntry(header, RPMTAG_ARCHIVESIZE,
RPM_INT32_TYPE, &archiveSize, 1);
-
- /* Rewind and rewrite the Header */
lseek(fd, 0, SEEK_SET);
headerWrite(fd, header, HEADER_MAGIC_YES);
-
+
close(fd);
-
- /* Now write the lead */
- if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
- fprintf(stderr, "Could not open %s\n", filename);
+
+ /* Open the output file */
+ if ((fd = open(fileName, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
+ rpmError(RPMERR_CREATE, "Could not open %s\n", fileName);
unlink(sigtarget);
free(sigtarget);
- unlink(filename);
- return 1;
+ return RPMERR_CREATE;
}
- if (writeMagic(fd, name, type)) {
+
+ /* Now write the lead */
+ headerGetEntry(header, RPMTAG_NAME, NULL, (void **)&name, NULL);
+ headerGetEntry(header, RPMTAG_VERSION, NULL, (void **)&version, NULL);
+ headerGetEntry(header, RPMTAG_RELEASE, NULL, (void **)&release, NULL);
+ sprintf(buf, "%s-%s-%s", name, version, release);
+ rpmGetArchInfo(NULL, &arch);
+ rpmGetOsInfo(NULL, &os);
+ lead.major = RPM_MAJOR_NUMBER;
+ lead.minor = 0;
+ lead.type = type;
+ lead.archnum = arch;
+ lead.osnum = os;
+ lead.signature_type = RPMSIG_HEADERSIG; /* New-style signature */
+ strncpy(lead.name, buf, sizeof(lead.name));
+ if (writeLead(fd, &lead)) {
+ rpmError(RPMERR_NOSPACE, "Unable to write package: %s",
+ strerror(errno));
close(fd);
unlink(sigtarget);
free(sigtarget);
- unlink(filename);
- return 1;
+ unlink(fileName);
+ return rc;
}
/* Generate the signature */
sigtype = rpmLookupSignatureType();
- rpmMessage(RPMMESS_VERBOSE, "Generating signature: %d\n", sigtype);
fflush(stdout);
sig = rpmNewSignature();
rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
- if (sigtype>0) {
+ if (sigtype > 0) {
+ rpmMessage(RPMMESS_NORMAL, "Generating signature: %d\n", sigtype);
rpmAddSignature(sig, sigtarget, sigtype, passPhrase);
}
- if (rpmWriteSignature(fd, sig)) {
+ if ((rc = rpmWriteSignature(fd, sig))) {
close(fd);
unlink(sigtarget);
free(sigtarget);
- unlink(filename);
+ unlink(fileName);
rpmFreeSignature(sig);
- return 1;
+ return rc;
}
rpmFreeSignature(sig);
-
+
/* Append the header and archive */
ifd = open(sigtarget, O_RDONLY);
- while ((count = read(ifd, buffer, sizeof(buffer))) > 0) {
- if (count == -1) {
- perror("Couldn't read sigtarget");
+ while ((count = read(ifd, buf, sizeof(buf))) > 0) {
+ if (count == -1) {
+ rpmError(RPMERR_READERROR, "Unable to read sigtarget: %s",
+ strerror(errno));
close(ifd);
close(fd);
unlink(sigtarget);
free(sigtarget);
- unlink(filename);
- return 1;
- }
- if (write(fd, buffer, count) < 0) {
- perror("Couldn't write package");
+ unlink(fileName);
+ return RPMERR_READERROR;
+ }
+ if (write(fd, buf, count) < 0) {
+ rpmError(RPMERR_NOSPACE, "Unable to write package: %s",
+ strerror(errno));
close(ifd);
close(fd);
unlink(sigtarget);
free(sigtarget);
- unlink(filename);
- return 1;
- }
+ unlink(fileName);
+ return RPMERR_NOSPACE;
+ }
}
close(ifd);
close(fd);
unlink(sigtarget);
free(sigtarget);
- rpmMessage(RPMMESS_VERBOSE, "Wrote: %s\n", filename);
-
- return 0;
-}
-
-static int writeMagic(int fd, char *name,
- unsigned short type)
-{
- struct rpmlead lead;
- int arch, os;
-
- rpmGetArchInfo(NULL, &arch);
- rpmGetOsInfo(NULL, &os);
-
- /* There are the Major and Minor numbers */
- lead.major = 3;
- lead.minor = 0;
- lead.type = type;
- lead.archnum = arch;
- lead.osnum = os;
- lead.signature_type = RPMSIG_HEADERSIG; /* New-style signature */
- strncpy(lead.name, name, sizeof(lead.name));
- memset(lead.reserved, 0, sizeof(lead.reserved));
-
- writeLead(fd, &lead);
+ rpmMessage(RPMMESS_NORMAL, "Wrote: %s\n", fileName);
return 0;
}
-static int cpio_gzip(int fd, char *tempdir, char *writePtr,
- int *archiveSize, char *prefix)
+static int cpio_gzip(int fd, struct cpioFileMapping *cpioList,
+ int cpioCount, int *archiveSize)
{
- int gzipPID;
- int toGzip[2];
- int rc;
- char * gzipbin;
- char * writebuf;
- char * chptr;
- int numMappings;
- struct cpioFileMapping * cpioList;
- int status;
+ char *gzipbin;
void *oldhandler;
- char savecwd[1024];
- char * failedFile;
+ int rc, gzipPID, toGzip[2], status;
+ char *failedFile;
gzipbin = rpmGetVar(RPMVAR_GZIPBIN);
-
- numMappings = 0;
- chptr = writePtr;
- while (chptr && *chptr) {
- numMappings++;
- chptr = strchr(chptr, '\n');
- if (chptr) *chptr++ = '\n';
- }
-
- writebuf = alloca(strlen(writePtr) + 1);
- strcpy(writebuf, writePtr);
-
- cpioList = alloca(sizeof(*cpioList) * numMappings);
- chptr = writebuf;
- numMappings = 0;
- while (chptr && *chptr) {
- cpioList[numMappings].fsPath = chptr;
- cpioList[numMappings].mapFlags = tempdir ? CPIO_FOLLOW_SYMLINKS : 0;
-
- chptr = strchr(chptr, '\n');
- if (chptr) *chptr++ = '\0';
-
- /* hack */
- if (!strlen(cpioList[numMappings].fsPath)) {
- cpioList[numMappings].fsPath = ".";
- }
-
- numMappings++;
- }
-
oldhandler = signal(SIGPIPE, SIG_IGN);
- pipe(toGzip);
-
/* GZIP */
+ pipe(toGzip);
if (!(gzipPID = fork())) {
close(toGzip[1]);
@@ -248,520 +295,105 @@ static int cpio_gzip(int fd, char *tempdir, char *writePtr,
rpmError(RPMERR_EXEC, "Couldn't exec gzip");
_exit(RPMERR_EXEC);
}
+ close(toGzip[0]);
if (gzipPID < 0) {
+ close(toGzip[1]);
rpmError(RPMERR_FORK, "Couldn't fork gzip");
return RPMERR_FORK;
}
- close(toGzip[0]);
-
- getcwd(savecwd, 1024);
-
- if (tempdir) {
- chdir(tempdir);
- } else if (rpmGetVar(RPMVAR_ROOT)) {
- if (chdir(rpmGetVar(RPMVAR_ROOT))) {
- rpmError(RPMERR_EXEC, "Couldn't chdir to %s",
- rpmGetVar(RPMVAR_ROOT));
- exit(RPMERR_EXEC);
- }
- } else {
- /* This is important! */
- chdir("/");
- }
- if (prefix) {
- if (chdir(prefix)) {
- rpmError(RPMERR_EXEC, "Couldn't chdir to %s", prefix);
- _exit(RPMERR_EXEC);
- }
- }
-
- rc = cpioBuildArchive(toGzip[1], cpioList, numMappings, NULL, NULL,
+ rc = cpioBuildArchive(fd, cpioList, cpioCount, NULL, NULL,
archiveSize, &failedFile);
- chdir(savecwd);
-
- close(toGzip[1]); /* Terminates the gzip process */
-
+ close(toGzip[1]);
signal(SIGPIPE, oldhandler);
-
waitpid(gzipPID, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status)) {
- rpmError(RPMERR_GZIP, "gzip failed");
+ rpmError(RPMERR_GZIP, "Execution of gzip failed");
return 1;
}
if (rc) {
if (rc & CPIO_CHECK_ERRNO)
- rpmError(RPMERR_CPIO, "cpio failed on file %s: %d: %s", failedFile,
- rc, strerror(errno));
+ rpmError(RPMERR_CPIO, "cpio failed on file %s: %s",
+ failedFile, strerror(errno));
else
- rpmError(RPMERR_CPIO, "cpio failed on file %s: %d", failedFile, rc);
+ rpmError(RPMERR_CPIO, "cpio failed on file %s: %d",
+ failedFile, rc);
return 1;
}
return 0;
}
-
-int packageBinaries(Spec s, char *passPhrase, int doPackage)
+static int addFileToTag(Spec spec, char *file, Header h, int tag)
{
- char name[1024];
- char *nametmp;
- char filename[1024];
- char sourcerpm[1024];
- char * binrpm;
- char *icon;
- int iconFD;
- struct stat statbuf;
- struct PackageRec *pr;
- Header outHeader;
- HeaderIterator headerIter;
- int_32 tag, type, c;
- void *ptr;
- char *version;
- char *release;
- char *vendor;
- char *dist;
- char *packager;
- char *packageVersion, *packageRelease;
- char *prefix, *prefixSave;
- char * arch, * os;
- char * binformat, * errorString;
- int prefixLen;
- int size;
- StringBuf cpioFileList;
- char **farray, *file;
- int count;
- int *fflagarray;
-
- if (!headerGetEntry(s->packages->header, RPMTAG_VERSION, NULL,
- (void *) &version, NULL)) {
- rpmError(RPMERR_BADSPEC, "No version field");
- return RPMERR_BADSPEC;
- }
- if (!headerGetEntry(s->packages->header, RPMTAG_RELEASE, NULL,
- (void *) &release, NULL)) {
- rpmError(RPMERR_BADSPEC, "No release field");
- return RPMERR_BADSPEC;
- }
- /* after the headerGetEntry() these are just pointers into the */
- /* header structure, which can be moved around by headerAddEntry */
- version = strdup(version);
- release = strdup(release);
-
- sprintf(sourcerpm, "%s-%s-%s.%ssrc.rpm", s->name, version, release,
- (s->numNoPatch + s->numNoSource) ? "no" : "");
-
- vendor = NULL;
- if (!headerIsEntry(s->packages->header, RPMTAG_VENDOR)) {
- vendor = rpmGetVar(RPMVAR_VENDOR);
- }
- dist = NULL;
- if (!headerIsEntry(s->packages->header, RPMTAG_DISTRIBUTION)) {
- dist = rpmGetVar(RPMVAR_DISTRIBUTION);
+ StringBuf sb;
+ char *s;
+ char buf[BUFSIZ];
+ FILE *f;
+
+ sb = newStringBuf();
+ if (headerGetEntry(h, tag, NULL, (void **)&s, NULL)) {
+ appendLineStringBuf(sb, s);
+ headerRemoveEntry(h, tag);
+ }
+ sprintf(buf, "%s/%s/%s", rpmGetVar(RPMVAR_BUILDDIR),
+ spec->buildSubdir, file);
+ if ((f = fopen(buf, "r")) == NULL) {
+ freeStringBuf(sb);
+ return 1;
}
- packager = NULL;
- if (!headerIsEntry(s->packages->header, RPMTAG_PACKAGER)) {
- packager = rpmGetVar(RPMVAR_PACKAGER);
- }
-
- /* Look through for each package */
- pr = s->packages;
- while (pr) {
- /* A file count of -1 means no package */
- if (pr->files == -1) {
- pr = pr->next;
- continue;
- }
-
- /* Handle subpackage version/release overrides */
- if (!headerGetEntry(pr->header, RPMTAG_VERSION, NULL,
- (void *) &packageVersion, NULL)) {
- packageVersion = version;
- }
- if (!headerGetEntry(pr->header, RPMTAG_RELEASE, NULL,
- (void *) &packageRelease, NULL)) {
- packageRelease = release;
- }
- /* after the headerGetEntry() these are just pointers into the */
- /* header structure, which can be moved around by headerAddEntry */
- packageVersion = strdup(packageVersion);
- packageRelease = strdup(packageRelease);
-
- /* Figure out the name of this package */
- if (!headerGetEntry(pr->header, RPMTAG_NAME, NULL, (void *)&nametmp, NULL)) {
- rpmError(RPMERR_INTERNAL, "Package has no name!");
- return RPMERR_INTERNAL;
- }
- sprintf(name, "%s-%s-%s", nametmp, packageVersion, packageRelease);
-
- if (doPackage == PACK_PACKAGE) {
- rpmMessage(RPMMESS_VERBOSE, "Binary Packaging: %s\n", name);
- } else {
- rpmMessage(RPMMESS_VERBOSE, "File List Check: %s\n", name);
- }
-
- /**** Generate the Header ****/
-
- /* Here's the plan: copy the package's header, */
- /* then add entries from the primary header */
- /* that don't already exist. */
- outHeader = headerCopy(pr->header);
- headerIter = headerInitIterator(s->packages->header);
- while (headerNextIterator(headerIter, &tag, &type, &ptr, &c)) {
- /* Some tags we don't copy */
- switch (tag) {
- case RPMTAG_PREIN:
- case RPMTAG_POSTIN:
- case RPMTAG_PREUN:
- case RPMTAG_POSTUN:
- case RPMTAG_PREINPROG:
- case RPMTAG_POSTINPROG:
- case RPMTAG_PREUNPROG:
- case RPMTAG_POSTUNPROG:
- case RPMTAG_VERIFYSCRIPT:
- continue;
- break; /* Shouldn't need this */
- default:
- if (! headerIsEntry(outHeader, tag)) {
- headerAddEntry(outHeader, tag, type, ptr, c);
- }
- }
- }
- headerFreeIterator(headerIter);
-
- headerRemoveEntry(outHeader, RPMTAG_BUILDARCHS);
-
- rpmGetArchInfo(&arch, NULL);
- rpmGetOsInfo(&os, NULL);
-
- /* Add some final entries to the header */
- headerAddEntry(outHeader, RPMTAG_OS, RPM_STRING_TYPE, os, 1);
- headerAddEntry(outHeader, RPMTAG_ARCH, RPM_STRING_TYPE, arch, 1);
- headerAddEntry(outHeader, RPMTAG_BUILDTIME, RPM_INT32_TYPE, getBuildTime(), 1);
- headerAddEntry(outHeader, RPMTAG_BUILDHOST, RPM_STRING_TYPE, buildHost(), 1);
- headerAddEntry(outHeader, RPMTAG_SOURCERPM, RPM_STRING_TYPE, sourcerpm, 1);
- headerAddEntry(outHeader, RPMTAG_RPMVERSION, RPM_STRING_TYPE, VERSION, 1);
- if (pr->icon) {
- sprintf(filename, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), pr->icon);
- stat(filename, &statbuf);
- icon = malloc(statbuf.st_size);
- iconFD = open(filename, O_RDONLY, 0644);
- read(iconFD, icon, statbuf.st_size);
- close(iconFD);
- if (! strncmp(icon, "GIF", 3)) {
- headerAddEntry(outHeader, RPMTAG_GIF, RPM_BIN_TYPE,
- icon, statbuf.st_size);
- } else if (! strncmp(icon, "/* XPM", 6)) {
- headerAddEntry(outHeader, RPMTAG_XPM, RPM_BIN_TYPE,
- icon, statbuf.st_size);
- } else {
- rpmError(RPMERR_BADSPEC, "Unknown icon type");
- return 1;
- }
- free(icon);
- }
- if (vendor) {
- headerAddEntry(outHeader, RPMTAG_VENDOR, RPM_STRING_TYPE, vendor, 1);
- }
- if (dist) {
- headerAddEntry(outHeader, RPMTAG_DISTRIBUTION, RPM_STRING_TYPE, dist, 1);
- }
- if (packager) {
- headerAddEntry(outHeader, RPMTAG_PACKAGER, RPM_STRING_TYPE, packager, 1);
- }
-
- /**** Process the file list ****/
-
- prefixSave = prefix = NULL;
- prefixLen = 0;
- if (headerGetEntry(outHeader, RPMTAG_DEFAULTPREFIX,
- NULL, (void **)&prefix, NULL)) {
- /* after the headerGetEntry() this is just pointers into the */
- /* header structure, which can be moved around by headerAddEntry */
- prefixSave = prefix = strdup(prefix);
- while (*prefix && (*prefix == '/')) {
- prefix++;
- }
- if (! *prefix) {
- prefix = NULL;
- prefixLen = 0;
- } else {
- prefixLen = strlen(prefix);
- rpmMessage(RPMMESS_VERBOSE, "Package Prefix = %s\n", prefix);
- }
- }
-
- if (process_filelist(outHeader, pr, pr->filelist, &size, nametmp,
- packageVersion, packageRelease, RPMLEAD_BINARY,
- prefix, NULL)) {
- return 1;
- }
-
- if (!headerGetEntry(outHeader, RPMTAG_FILENAMES, NULL,
- (void **) &farray, &count)) {
- /* count may already be 0, but this is safer */
- count = 0;
- }
- headerGetEntry(outHeader, RPMTAG_FILEFLAGS, NULL,
- (void **) &fflagarray, NULL);
-
- cpioFileList = newStringBuf();
- while (count--) {
- file = *farray++;
- while (*file == '/') {
- file++; /* Skip leading "/" */
- }
- if (prefix) {
- if (strncmp(prefix, file, prefixLen)) {
- rpmError(RPMERR_BADSPEC, "File doesn't match prefix (%s): %s",
- prefix, file);
- return 1;
- }
- file += prefixLen;
- if (*file) {
- file++; /* 1 for "/" */
- }
- }
-
- if (! (*fflagarray & RPMFILE_GHOST)) {
- appendLineStringBuf(cpioFileList, file);
- }
- fflagarray++;
- }
-
- /* Generate any automatic require/provide entries */
- /* Then add the whole thing to the header */
- if (s->autoReqProv) {
- generateAutoReqProv(outHeader, pr);
- }
- processReqProv(outHeader, pr);
-
- /* Generate the any trigger entries */
- generateTriggerEntries(outHeader, pr);
-
- /* And add the final Header entry */
- headerAddEntry(outHeader, RPMTAG_SIZE, RPM_INT32_TYPE, &size, 1);
-
- /**** Make the RPM ****/
-
- /* Make the output RPM filename */
- if (doPackage == PACK_PACKAGE) {
- binformat = rpmGetVar(RPMVAR_RPMFILENAME);
- binrpm = headerSprintf(outHeader, binformat, rpmTagTable,
- rpmHeaderFormats, &errorString);
-
- if (!binrpm) {
- rpmError(RPMERR_BADFILENAME, "could not generate output "
- "filename for package %s: %s\n", name, binrpm);
- }
-
- sprintf(filename, "%s/%s", rpmGetVar(RPMVAR_RPMDIR), binrpm);
- free(binrpm);
-
- if (generateRPM(name, filename, RPMLEAD_BINARY, outHeader, NULL,
- getStringBuf(cpioFileList), passPhrase, prefix)) {
- /* Build failed */
- return 1;
- }
- }
-
- freeStringBuf(cpioFileList);
- headerFree(outHeader);
-
- if (prefixSave)
- free(prefixSave);
- free(packageVersion);
- free(packageRelease);
-
- pr = pr->next;
+ while (fgets(buf, sizeof(buf), f)) {
+ expandMacros(&spec->macros, buf);
+ appendStringBuf(sb, buf);
}
+ fclose(f);
+
+ headerAddEntry(h, tag, RPM_STRING_TYPE, getStringBuf(sb), 1);
- free(version);
- free(release);
-
+ freeStringBuf(sb);
return 0;
}
-/**************** SOURCE PACKAGING ************************/
-
-int packageSource(Spec s, char *passPhrase)
+static int processScriptFiles(Spec spec, Package pkg)
{
- struct sources *source;
- struct PackageRec *package;
- char *tempdir;
- char src[1024], dest[1024], fullname[1024], filename[1024], specFile[1024];
- char *version;
- char *release;
- char *vendor;
- char *dist;
- char *p;
- Header outHeader;
- StringBuf filelist;
- StringBuf cpioFileList;
- int size;
- char **sources;
- char **patches;
- char * arch, * os;
- int scount, pcount;
- int skipi;
- int_32 *skip;
-
- /**** Create links for all the sources ****/
-
- tempdir = tempnam(rpmGetVar(RPMVAR_TMPPATH), "rpmbuild");
- mkdir(tempdir, 0700);
-
- filelist = newStringBuf(); /* List in the header */
- cpioFileList = newStringBuf(); /* List for cpio */
-
- sources = malloc((s->numSources+1) * sizeof(char *));
- patches = malloc((s->numPatches+1) * sizeof(char *));
-
- /* Link in the spec file and all the sources */
- p = strrchr(s->specfile, '/');
- sprintf(dest, "%s%s", tempdir, p);
- strcpy(specFile, dest);
- symlink(s->specfile, dest);
- appendLineStringBuf(filelist, dest);
- appendLineStringBuf(cpioFileList, p+1);
- source = s->sources;
- scount = 0;
- pcount = 0;
- while (source) {
- if (source->ispatch) {
- skipi = s->numNoPatch - 1;
- skip = s->noPatch;
- } else {
- skipi = s->numNoSource - 1;
- skip = s->noSource;
- }
- while (skipi >= 0) {
- if (skip[skipi] == source->num) {
- break;
- }
- skipi--;
- }
- sprintf(src, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), source->source);
- sprintf(dest, "%s/%s", tempdir, source->source);
- if (skipi < 0) {
- symlink(src, dest);
- appendLineStringBuf(cpioFileList, source->source);
- } else {
- rpmMessage(RPMMESS_VERBOSE, "Skipping source/patch (%d): %s\n",
- source->num, source->source);
- }
- appendLineStringBuf(filelist, src);
- if (source->ispatch) {
- patches[pcount++] = source->fullSource;
- } else {
- sources[scount++] = source->fullSource;
+ if (pkg->preInFile) {
+ if (addFileToTag(spec, pkg->preInFile, pkg->header, RPMTAG_PREIN)) {
+ rpmError(RPMERR_BADFILENAME,
+ "Could not open PreIn file: %s", pkg->preInFile);
+ return RPMERR_BADFILENAME;
}
- source = source->next;
}
- /* ... and icons */
- package = s->packages;
- while (package) {
- if (package->icon) {
- sprintf(src, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), package->icon);
- sprintf(dest, "%s/%s", tempdir, package->icon);
- appendLineStringBuf(filelist, dest);
- appendLineStringBuf(cpioFileList, package->icon);
- symlink(src, dest);
+ if (pkg->preUnFile) {
+ if (addFileToTag(spec, pkg->preUnFile, pkg->header, RPMTAG_PREUN)) {
+ rpmError(RPMERR_BADFILENAME,
+ "Could not open PreUn file: %s", pkg->preUnFile);
+ return RPMERR_BADFILENAME;
}
- package = package->next;
}
-
- /**** Generate the Header ****/
-
- if (!headerGetEntry(s->packages->header, RPMTAG_VERSION, NULL,
- (void *) &version, NULL)) {
- rpmError(RPMERR_BADSPEC, "No version field");
- return RPMERR_BADSPEC;
- }
- if (!headerGetEntry(s->packages->header, RPMTAG_RELEASE, NULL,
- (void *) &release, NULL)) {
- rpmError(RPMERR_BADSPEC, "No release field");
- return RPMERR_BADSPEC;
- }
-
- rpmGetArchInfo(&arch, NULL);
- rpmGetOsInfo(&os, NULL);
-
- outHeader = headerCopy(s->packages->header);
- headerAddEntry(outHeader, RPMTAG_OS, RPM_STRING_TYPE, os, 1);
- headerAddEntry(outHeader, RPMTAG_ARCH, RPM_STRING_TYPE, arch, 1);
- headerAddEntry(outHeader, RPMTAG_BUILDTIME, RPM_INT32_TYPE, getBuildTime(), 1);
- headerAddEntry(outHeader, RPMTAG_BUILDHOST, RPM_STRING_TYPE, buildHost(), 1);
- headerAddEntry(outHeader, RPMTAG_RPMVERSION, RPM_STRING_TYPE, VERSION, 1);
- if (scount)
- headerAddEntry(outHeader, RPMTAG_SOURCE, RPM_STRING_ARRAY_TYPE, sources, scount);
- if (pcount)
- headerAddEntry(outHeader, RPMTAG_PATCH, RPM_STRING_ARRAY_TYPE, patches, pcount);
- if (s->numNoSource) {
- headerAddEntry(outHeader, RPMTAG_NOSOURCE, RPM_INT32_TYPE, s->noSource,
- s->numNoSource);
- }
- if (s->numNoPatch) {
- headerAddEntry(outHeader, RPMTAG_NOPATCH, RPM_INT32_TYPE, s->noPatch,
- s->numNoPatch);
- }
- if (!headerIsEntry(s->packages->header, RPMTAG_VENDOR)) {
- if ((vendor = rpmGetVar(RPMVAR_VENDOR))) {
- headerAddEntry(outHeader, RPMTAG_VENDOR, RPM_STRING_TYPE, vendor, 1);
+ if (pkg->postInFile) {
+ if (addFileToTag(spec, pkg->postInFile, pkg->header, RPMTAG_POSTIN)) {
+ rpmError(RPMERR_BADFILENAME,
+ "Could not open PostIn file: %s", pkg->postInFile);
+ return RPMERR_BADFILENAME;
}
}
- if (!headerIsEntry(s->packages->header, RPMTAG_DISTRIBUTION)) {
- if ((dist = rpmGetVar(RPMVAR_DISTRIBUTION))) {
- headerAddEntry(outHeader, RPMTAG_DISTRIBUTION, RPM_STRING_TYPE, dist, 1);
+ if (pkg->postUnFile) {
+ if (addFileToTag(spec, pkg->postUnFile, pkg->header, RPMTAG_POSTUN)) {
+ rpmError(RPMERR_BADFILENAME,
+ "Could not open PostUn file: %s", pkg->postUnFile);
+ return RPMERR_BADFILENAME;
}
}
-
- /* Process the file list */
- if (process_filelist(outHeader, NULL, filelist, &size,
- s->name, version, release, RPMLEAD_SOURCE,
- NULL, specFile)) {
- return 1;
- }
-
- /* And add the final Header entry */
- headerAddEntry(outHeader, RPMTAG_SIZE, RPM_INT32_TYPE, &size, 1);
-
- /**** Make the RPM ****/
-
- sprintf(fullname, "%s-%s-%s", s->name, version, release);
- sprintf(filename, "%s/%s.%ssrc.rpm", rpmGetVar(RPMVAR_SRPMDIR), fullname,
- (s->numNoPatch + s->numNoSource) ? "no" : "");
- rpmMessage(RPMMESS_VERBOSE, "Source Packaging: %s\n", fullname);
-
- if (generateRPM(fullname, filename, RPMLEAD_SOURCE, outHeader,
- tempdir, getStringBuf(cpioFileList), passPhrase, NULL)) {
- return 1;
- }
-
- /**** Now clean up ****/
-
- freeStringBuf(filelist);
- freeStringBuf(cpioFileList);
-
- source = s->sources;
- while (source) {
- sprintf(dest, "%s/%s", tempdir, source->source);
- unlink(dest);
- source = source->next;
- }
- package = s->packages;
- while (package) {
- if (package->icon) {
- sprintf(dest, "%s/%s", tempdir, package->icon);
- unlink(dest);
+ if (pkg->verifyFile) {
+ if (addFileToTag(spec, pkg->verifyFile, pkg->header,
+ RPMTAG_VERIFYSCRIPT)) {
+ rpmError(RPMERR_BADFILENAME,
+ "Could not open VerifyScript file: %s", pkg->verifyFile);
+ return RPMERR_BADFILENAME;
}
- package = package->next;
}
- sprintf(dest, "%s%s", tempdir, strrchr(s->specfile, '/'));
- unlink(dest);
- rmdir(tempdir);
-
+
return 0;
}
diff --git a/build/pack.h b/build/pack.h
index d144484cf..51905e209 100644
--- a/build/pack.h
+++ b/build/pack.h
@@ -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);
diff --git a/build/package.c b/build/package.c
new file mode 100644
index 000000000..9184282a1
--- /dev/null
+++ b/build/package.c
@@ -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);
+}
diff --git a/build/package.h b/build/package.h
new file mode 100644
index 000000000..908638612
--- /dev/null
+++ b/build/package.h
@@ -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
diff --git a/build/parse.h b/build/parse.h
new file mode 100644
index 000000000..4b748282a
--- /dev/null
+++ b/build/parse.h
@@ -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
diff --git a/build/parseBuildInstallClean.c b/build/parseBuildInstallClean.c
new file mode 100644
index 000000000..fbb94401c
--- /dev/null
+++ b/build/parseBuildInstallClean.c
@@ -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;
+}
diff --git a/build/parseChangelog.c b/build/parseChangelog.c
new file mode 100644
index 000000000..7de812cf3
--- /dev/null
+++ b/build/parseChangelog.c
@@ -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;
+}
diff --git a/build/parseDescription.c b/build/parseDescription.c
new file mode 100644
index 000000000..01af29edc
--- /dev/null
+++ b/build/parseDescription.c
@@ -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;
+}
diff --git a/build/parseFiles.c b/build/parseFiles.c
new file mode 100644
index 000000000..68cd72e84
--- /dev/null
+++ b/build/parseFiles.c
@@ -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;
+}
diff --git a/build/parsePreamble.c b/build/parsePreamble.c
new file mode 100644
index 000000000..cf87f9ef2
--- /dev/null
+++ b/build/parsePreamble.c
@@ -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;
+}
diff --git a/build/parsePrep.c b/build/parsePrep.c
new file mode 100644
index 000000000..bf611ea64
--- /dev/null
+++ b/build/parsePrep.c
@@ -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;
+}
diff --git a/build/parseReqs.c b/build/parseReqs.c
new file mode 100644
index 000000000..87241ade2
--- /dev/null
+++ b/build/parseReqs.c
@@ -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;
+}
diff --git a/build/parseScript.c b/build/parseScript.c
new file mode 100644
index 000000000..b2f604f37
--- /dev/null
+++ b/build/parseScript.c
@@ -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;
+}
diff --git a/build/parseSpec.c b/build/parseSpec.c
new file mode 100644
index 000000000..a3badbb18
--- /dev/null
+++ b/build/parseSpec.c
@@ -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);
+}
diff --git a/build/trigger.c b/build/parseTrigger.c
index ea6e94a2d..1d18c1a77 100644
--- a/build/trigger.c
+++ b/build/parseTrigger.c
@@ -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"
-
-#define FREE(x) { if (x) free(x); }
-#define CHUNK 8
+/* %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. */
+
+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)
diff --git a/build/part.c b/build/part.c
new file mode 100644
index 000000000..ca3ce2e6b
--- /dev/null
+++ b/build/part.c
@@ -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;
+ }
+}
+
diff --git a/build/part.h b/build/part.h
new file mode 100644
index 000000000..6ddae3238
--- /dev/null
+++ b/build/part.h
@@ -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
diff --git a/build/read.c b/build/read.c
new file mode 100644
index 000000000..b5790fe3a
--- /dev/null
+++ b/build/read.c
@@ -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;
+}
diff --git a/build/read.h b/build/read.h
new file mode 100644
index 000000000..041125d98
--- /dev/null
+++ b/build/read.h
@@ -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
diff --git a/build/reqprov.c b/build/reqprov.c
index b06e930ea..0a2abfb6f 100644
--- a/build/reqprov.c
+++ b/build/reqprov.c
@@ -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;
- }
- if (rd) {
- /* already there */
- rpmMessage(RPMMESS_DEBUG, "Already Got: %s\n", name);
- return 0;
- }
+ char **names;
+ char **versions = NULL;
+ int *flags = NULL;
+ int nametag = 0;
+ int versiontag = 0;
+ int flagtag = 0;
+ int len;
+ int extra = 0;
- 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 (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++;
+ 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 {
- rpmMessage(RPMMESS_DEBUG, "Adding require: %s\n", name);
- p->numReq++;
+ nametag = RPMTAG_REQUIRENAME;
+ versiontag = RPMTAG_REQUIREVERSION;
+ flagtag = RPMTAG_REQUIREFLAGS;
}
- 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 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;
+ flag = (flag & RPMSENSE_SENSEMASK) | extra;
+ if (!version) {
+ version = "";
}
-
- 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;
+ 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);
}
-
- /* 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);
+ 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;
}
- 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;
+ FREE(names);
+ FREE(versions);
}
- waitpid(progPID, &status, 0);
- if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
- rpmError(RPMERR_EXEC, "%s failed", argv[0]);
- return NULL;
+
+ 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 readBuff;
+ return 0;
}
-int generateAutoReqProv(Header header, struct PackageRec *p)
+int generateAutoReqProv(Spec spec, Package pkg,
+ struct cpioFileMapping *cpioList, int cpioCount)
{
- 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];
-
- rpmMessage(RPMMESS_VERBOSE, "Finding dependencies...\n");
-
- /*** Get root directory ***/
-
- if (rpmGetVar(RPMVAR_ROOT)) {
- strcpy(dir, rpmGetVar(RPMVAR_ROOT));
- } else {
- strcpy(dir, "/");
- }
+ StringBuf readBuf;
+ char *argv[2];
+ char **f, **fsave;
- /*** Generate File List ***/
-
- if (!headerGetEntry(header, RPMTAG_FILENAMES, NULL, (void **) &f, &count)) {
- return 0;
- }
- if (!count) {
+ if (!cpioCount) {
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);
- }
- if (fsave) {
- free(fsave);
+ while (cpioCount--) {
+ writeBytes += strlen(cpioList->fsPath) + 1;
+ appendLineStringBuf(writeBuf, cpioList->fsPath);
+ cpioList++;
}
- 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;
-
- 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;
+ int startedPreReq = 0;
+ int startedReq = 0;
+
+ 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);
- }
-
- 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;
+ rpmMessage(RPMMESS_NORMAL, "\n");
+ FREE(names);
+ }
+
+ 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;
+ }
+ rpmMessage(RPMMESS_NORMAL, " %s", names[x]);
}
- rd = rd->next;
+ x++;
}
- 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);
+ rpmMessage(RPMMESS_NORMAL, "\n");
+ x = 0;
+ while (x < count) {
+ if (! (flags[x] & RPMSENSE_PREREQ)) {
+ if (! startedReq) {
+ rpmMessage(RPMMESS_NORMAL, "Requires:");
+ startedReq = 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");
+ FREE(names);
}
- return 0;
}
diff --git a/build/reqprov.h b/build/reqprov.h
index f45e8a6ad..7069c47d3 100644
--- a/build/reqprov.h
+++ b/build/reqprov.h
@@ -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
diff --git a/build/spec.c b/build/spec.c
index 6bc047617..1be377c75 100644
--- a/build/spec.c
+++ b/build/spec.c
@@ -1,1750 +1,289 @@
-/* RPM - Copyright (C) 1995 Red Hat Software
- *
- * spec.c - routines for parsing a spec file
- */
-
-/*****************************
-TODO:
-
-. should be able to drop the -n in non-%package parts
-
-******************************/
-
-#include "config.h"
-#include "miscfn.h"
-
-#if HAVE_ALLOCA_H
-# include <alloca.h>
-#endif
-
#include <stdlib.h>
+#include <malloc.h>
#include <string.h>
-#include <sys/types.h>
-#include <time.h>
-#include <sys/time.h>
-#include <limits.h>
-#include <ctype.h>
-#include "header.h"
#include "spec.h"
-#include "specP.h"
-#include "messages.h"
-#include "rpmlib.h"
-#include "stringbuf.h"
#include "misc.h"
-#include "reqprov.h"
-#include "trigger.h"
+#include "rpmlib.h"
+#include "package.h"
+#include "read.h"
+#include "files.h"
#include "macro.h"
-#define LINE_BUF_SIZE 1024
-#define FREE(x) { if (x) free(x); }
-
-static struct PackageRec *new_packagerec(void);
-static int read_line(FILE *f, char *line);
-static int match_arch(char *s);
-static int match_os(char *s);
-static void free_packagerec(struct PackageRec *p);
-static void generateNames(Spec s);
-static void reset_spec(void);
-static int find_preamble_line(char *line, char **s);
-static int check_part(char *line, char **s);
-static int lookup_package(Spec s, struct PackageRec **pr,
- char *name, int flags);
-static void dumpPackage(struct PackageRec *p, FILE *f);
-
-static int dateToTimet(const char * datestr, time_t * secs);
-static void addChangelogEntry(Header h, int time, char *name, char *text);
-static int addChangelog(Header h, StringBuf sb);
-
-static int parseProvides(struct PackageRec *p, char *line, int tag);
-static int parseRequiresConflicts(struct PackageRec *p, char *line,
- int flag);
-static void free_reqprov(struct ReqProv *p);
-static int noSourcePatch(Spec s, char *line, int_32 tag);
+static char *getSourceAux(Spec spec, int num, int flag, int full);
+static struct Source *findSource(Spec spec, int num, int flag);
-static void addListEntry(Header h, int_32 tag, char *line);
-static int finishCurrentPart(Spec spec, StringBuf sb,
- struct PackageRec *cur_package,
- int cur_part, char *triggerArgs,
- char *scriptProg);
-
-Spec parseSpecAux(FILE *f, char *specfile, char *buildRootOverride,
- char ***buildArchs);
-
-/**********************************************************************/
-/* */
-/* Source and patch structure creation/deletion/lookup */
-/* */
-/**********************************************************************/
-
-static int addSource(Spec spec, char *line)
+Spec newSpec(void)
{
- struct sources *p;
- char *s, *s1, c;
- char *file;
- unsigned long int x;
- char name[1024], expansion[1024];
-
- p = malloc(sizeof(struct sources));
- p->next = spec->sources;
- spec->sources = p;
-
- if (! strncasecmp(line, "source", 6)) {
- spec->numSources++;
- p->ispatch = 0;
- s = line + 6;
- } else if (! strncasecmp(line, "patch", 5)) {
- spec->numPatches++;
- p->ispatch = 1;
- s = line + 5;
- } else {
- rpmError(RPMERR_BADSPEC, "Not a source/patch line: %s\n", line);
- return(RPMERR_BADSPEC);
- }
-
- s += strspn(s, " \t\n");
- p->num = 0;
- if (*s != ':') {
- x = strspn(s, "0123456789");
- if (! x) {
- rpmError(RPMERR_BADSPEC, "Bad source/patch line: %s\n", line);
- return(RPMERR_BADSPEC);
- }
- c = s[x];
- s[x] = '\0';
- s1 = NULL;
- p->num = strtoul(s, &s1, 10);
- if ((*s1) || (s1 == s) || (p->num == ULONG_MAX)) {
- s[x] = c;
- rpmError(RPMERR_BADSPEC, "Bad source/patch number: %s\n", s);
- return(RPMERR_BADSPEC);
- }
- s[x] = c;
- s += x;
- /* skip spaces */
- s += strspn(s, " \t\n");
- }
+ Spec spec;
- if (*s != ':') {
- rpmError(RPMERR_BADSPEC, "Bad source/patch line: %s\n", line);
- return(RPMERR_BADSPEC);
- }
+ spec = (Spec)malloc(sizeof *spec);
- /* skip to actual source */
- s++;
- s += strspn(s, " \t\n");
+ spec->specFile = NULL;
+ spec->sourceRpmName = NULL;
+
+ spec->file = NULL;
+ spec->readBuf[0] = '\0';
+ spec->readPtr = NULL;
+ spec->line[0] = '\0';
+ spec->readStack = malloc(sizeof(struct ReadLevelEntry));
+ spec->readStack->next = NULL;
+ spec->readStack->reading = 1;
+
+ spec->prep = NULL;
+ spec->build = NULL;
+ spec->install = NULL;
+ spec->clean = NULL;
- file = strtok(s, " \t\n");
- if (! file) {
- rpmError(RPMERR_BADSPEC, "Bad source/patch line: %s\n", line);
- return(RPMERR_BADSPEC);
- }
- p->fullSource = strdup(file);
- p->source = strrchr(p->fullSource, '/');
- if (p->source) {
- p->source++;
- } else {
- p->source = p->fullSource;
- }
+ spec->sources = NULL;
+ spec->packages = NULL;
+ spec->noSource = 0;
+ spec->numSources = 0;
- sprintf(expansion, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), p->source);
- sprintf(name, "%s%d", (p->ispatch) ? "PATCH" : "SOURCE", p->num);
- addMacro(name, expansion);
- sprintf(name, "%sURL%d", (p->ispatch) ? "PATCH" : "SOURCE", p->num);
- addMacro(name, p->fullSource);
+ spec->sourceHeader = NULL;
+
+ spec->sourceCpioCount = 0;
+ spec->sourceCpioList = NULL;
- if (p->ispatch) {
- rpmMessage(RPMMESS_DEBUG, "Patch(%d) = %s\n", p->num, p->fullSource);
- } else {
- rpmMessage(RPMMESS_DEBUG, "Source(%d) = %s\n", p->num, p->fullSource);
- }
+ spec->gotBuildRoot = 0;
+ spec->buildRoot = NULL;
- return 0;
-}
-
-static void freeSources(Spec s)
-{
- struct sources *p1, *p2;
-
- p1 = s->sources;
- while (p1) {
- p2 = p1;
- p1 = p1->next;
- free(p2->fullSource);
- free(p2);
- }
-}
+ spec->buildSubdir = NULL;
-char *getSource(Spec s, int ispatch, int num)
-{
- struct sources *p = s->sources;
+ spec->docDir = NULL;
- while (p) {
- if ((ispatch == p->ispatch) &&
- (num == p->num)) {
- break;
- } else {
- p = p->next;
- }
- }
-
- if (p) {
- return(p->source);
- } else {
- return(NULL);
- }
-}
+ spec->passPhrase = NULL;
+ spec->timeCheck = 0;
+ spec->cookie = NULL;
-char *getFullSource(Spec s, int ispatch, int num)
-{
- struct sources *p = s->sources;
+ spec->buildRestrictions = headerNew();
+ spec->buildArchitectures = NULL;
+ spec->buildArchitectureCount = 0;
+ spec->inBuildArchitectures = 0;
+ spec->buildArchitectureSpecs = NULL;
- while (p) {
- if ((ispatch == p->ispatch) &&
- (num == p->num)) {
- break;
- } else {
- p = p->next;
- }
- }
+ initMacros(&spec->macros);
+
+ spec->autoReqProv = 1;
- if (p) {
- return(p->fullSource);
- } else {
- return(NULL);
- }
+ return spec;
}
-int noSourcePatch(Spec s, char *line, int_32 tag)
+void freeSpec(Spec spec)
{
- int_32 array[1024]; /* XXX - max 1024 sources or patches */
- int_32 num;
- int count;
- char *t, *te;
-
- if (((tag == RPMTAG_NOSOURCE) && s->numNoSource) ||
- ((tag == RPMTAG_NOPATCH) && s->numNoPatch)) {
- rpmError(RPMERR_BADSPEC, "Only one nosource/nopatch line allowed\n");
- return(RPMERR_BADSPEC);
- }
+ struct ReadLevelEntry *rl;
- count = 0;
- while ((t = strtok(line, ", \t"))) {
- num = strtoul(t, &te, 10);
- if ((*te) || (te == t) || (num == ULONG_MAX)) {
- rpmError(RPMERR_BADSPEC, "Bad source/patch number: %s\n", t);
- return(RPMERR_BADSPEC);
- }
- array[count++] = num;
- rpmMessage(RPMMESS_DEBUG, "Skipping source/patch number: %d\n", num);
- line = NULL;
- }
-
- if (count) {
- if (tag == RPMTAG_NOSOURCE) {
- s->numNoSource = count;
- s->noSource = malloc(sizeof(int_32) * count);
- memcpy(s->noSource, array, sizeof(int_32) * count);
- } else {
- s->numNoPatch = count;
- s->noPatch = malloc(sizeof(int_32) * count);
- memcpy(s->noPatch, array, sizeof(int_32) * count);
- }
+ freeStringBuf(spec->prep);
+ freeStringBuf(spec->build);
+ freeStringBuf(spec->install);
+ freeStringBuf(spec->clean);
+
+ FREE(spec->buildRoot);
+ FREE(spec->buildSubdir);
+ FREE(spec->specFile);
+ FREE(spec->sourceRpmName);
+ FREE(spec->docDir);
+
+ while (spec->readStack) {
+ rl = spec->readStack;
+ spec->readStack = spec->readStack->next;
+ free(rl);
}
-
- return 0;
-}
-
-/**********************************************************************/
-/* */
-/* Provide/Require handling */
-/* */
-/**********************************************************************/
-
-static void free_reqprov(struct ReqProv *p)
-{
- struct ReqProv *s;
- while (p) {
- s = p;
- p = p->next;
- FREE(s->name);
- FREE(s->version);
- free(s);
+ if (spec->sourceHeader) {
+ headerFree(spec->sourceHeader);
}
-}
-struct ReqComp 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},
+ freeCpioList(spec->sourceCpioList, spec->sourceCpioCount);
- { ">=", 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 },
-};
-
-static int parseRequiresConflicts(struct PackageRec *p, char *line,
- int flag)
-{
- char *req = NULL;
- char *version = NULL;
- int flags;
- struct ReqComp *rc;
-
- while (req || (req = strtok(line, " ,\t\n"))) {
- switch (flag) {
- case RPMTAG_CONFLICTFLAGS:
- flags = RPMSENSE_CONFLICTS;
- break;
- case RPMTAG_PREREQ:
- flags = RPMSENSE_PREREQ;
- break;
- default:
- flags = RPMSENSE_ANY;
- break;
- }
- if (flag == RPMTAG_CONFLICTFLAGS && req[0] == '/') {
- rpmError(RPMERR_BADSPEC,
- "No file names in Conflicts: %s", req);
- return RPMERR_BADSPEC;
- }
- 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,
- "No versions on file names in Requires: %s", req);
- return RPMERR_BADSPEC;
- }
- if (flag == RPMTAG_PREREQ) {
- rpmError(RPMERR_BADSPEC,
- "No versions in PreReq: %s", req);
- return RPMERR_BADSPEC;
- }
- /* read a version */
- flags |= rc->flags;
- version = strtok(NULL, " ,\t\n");
- }
- }
- if ((flags & RPMSENSE_SENSEMASK) && !version) {
- rpmError(RPMERR_BADSPEC, "Version required in require/conflict");
- return RPMERR_BADSPEC;
- }
-
- addReqProv(p, flags, req,
- (flags & RPMSENSE_SENSEMASK) ? version : NULL);
+ headerFree(spec->buildRestrictions);
+ FREE(spec->buildArchitectures);
- req = NULL;
- if (! (flags & RPMSENSE_SENSEMASK)) {
- /* No version -- we just read a name */
- req = version;
+ if (!spec->inBuildArchitectures) {
+ while (spec->buildArchitectureCount--) {
+ freeSpec(
+ spec->buildArchitectureSpecs[spec->buildArchitectureCount]);
}
- line = NULL;
}
-
- return 0;
-}
+ FREE(spec->buildArchitectures);
-static int parseProvides(struct PackageRec *p, char *line, int tag)
-{
- char *prov;
- int flags;
+ FREE(spec->passPhrase);
+ FREE(spec->cookie);
- flags = (tag == RPMTAG_PROVIDES) ? RPMSENSE_PROVIDES : RPMSENSE_OBSOLETES;
+ freeMacros(&spec->macros);
- while ((prov = strtok(line, " ,\t\n"))) {
- if (prov[0] == '/') {
- rpmError(RPMERR_BADSPEC,
- "No file names in %s: %s",
- (tag == RPMTAG_PROVIDES) ? "provides" : "obsoletes",
- prov);
- return RPMERR_BADSPEC;
- }
- addReqProv(p, flags, prov, NULL);
- line = NULL;
- }
- return 0;
-}
-
-/**********************************************************************/
-/* */
-/* Spec and package structure creation/deletion/lookup */
-/* */
-/**********************************************************************/
-
-static struct PackageRec *new_packagerec(void)
-{
- struct PackageRec *p = malloc(sizeof(struct PackageRec));
-
- p->subname = NULL;
- p->newname = NULL;
- p->icon = NULL;
- p->header = headerNew();
- p->filelist = newStringBuf();
- p->files = -1; /* -1 means no %files, thus no package */
- p->fileFile = NULL;
- p->doc = newStringBuf();
- p->reqprov = NULL;
- p->numReq = 0;
- p->numProv = 0;
- p->numConflict = 0;
- p->numPreReq = 0;
- p->numObsoletes = 0;
- p->trigger.alloced = 0;
- p->trigger.used = 0;
- p->trigger.triggerScripts = NULL;
- p->trigger.trigger = NULL;
- p->trigger.triggerCount = 0;
- p->next = NULL;
-
- return p;
-}
-
-void free_packagerec(struct PackageRec *p)
-{
- if (! p ) return;
+ freeSources(spec);
+ freePackages(spec);
+ closeSpec(spec);
- headerFree(p->header);
- freeStringBuf(p->filelist);
- freeStringBuf(p->doc);
- FREE(p->subname);
- FREE(p->newname);
- FREE(p->icon);
- FREE(p->fileFile);
- free_reqprov(p->reqprov);
- freeTriggers(p->trigger);
- if (p->next) {
- free_packagerec(p->next);
- }
- free(p);
+ free(spec);
}
-void freeSpec(Spec s)
+int addSource(Spec spec, Package pkg, char *field, int tag)
{
- FREE(s->name);
- FREE(s->specfile);
- FREE(s->noSource);
- FREE(s->noPatch);
- FREE(s->buildroot);
- FREE(s->buildArch);
- freeSources(s);
- freeStringBuf(s->prep);
- freeStringBuf(s->build);
- freeStringBuf(s->install);
- freeStringBuf(s->doc);
- freeStringBuf(s->clean);
- free_packagerec(s->packages);
- free(s);
-}
-
-#define LP_CREATE 1
-#define LP_FAIL_EXISTS (1 << 1)
-#define LP_SUBNAME (1 << 2)
-#define LP_NEWNAME (1 << 3)
-
-int lookup_package(Spec s, struct PackageRec **pr, char *name, int flags)
-{
- struct PackageRec *package;
- struct PackageRec **ppp;
-
- package = s->packages;
- while (package) {
- if (flags & LP_SUBNAME) {
- if (! package->subname) {
- package = package->next;
- continue;
- }
- if (! strcmp(package->subname, name)) {
- break;
- }
- } else if (flags & LP_NEWNAME) {
- if (! package->newname) {
- package = package->next;
- continue;
- }
- if (! strcmp(package->newname, name)) {
- break;
- }
- } else {
- /* Base package */
- if ((! package->newname) && (! package->subname)) {
- break;
- }
- }
- package = package->next;
- }
-
- if (package && (flags & LP_FAIL_EXISTS)) {
- return 0;
- }
-
- if (package) {
- *pr = package;
- return 1;
+ struct Source *p;
+ int flag = 0;
+ char *name = NULL;
+ char *nump, *fieldp = NULL;
+ char buf[BUFSIZ];
+ char expansion[BUFSIZ];
+ int num = 0;
+
+ switch (tag) {
+ case RPMTAG_SOURCE:
+ flag = RPMBUILD_ISSOURCE;
+ name = "source";
+ fieldp = spec->line + 6;
+ break;
+ case RPMTAG_PATCH:
+ flag = RPMBUILD_ISPATCH;
+ name = "patch";
+ fieldp = spec->line + 5;
+ break;
+ case RPMTAG_ICON:
+ flag = RPMBUILD_ISICON;
+ break;
}
- /* At this point the package does not exist */
-
- if (! (flags & LP_CREATE)) {
- return 0;
- }
+ /* Get the number */
+ if (tag != RPMTAG_ICON) {
+ /* We already know that a ':' exists, and that there */
+ /* are no spaces before it. */
- /* Create it */
- package = new_packagerec();
- if (name) {
- if (flags & LP_SUBNAME) {
- package->subname = strdup(name);
- } else if (flags & LP_NEWNAME) {
- package->newname = strdup(name);
+ nump = buf;
+ while (*fieldp != ':') {
+ *nump++ = *fieldp++;
}
- }
-
- /* Link it in to the spec */
- ppp = &(s->packages);
- while (*ppp) {
- ppp = &((*ppp)->next);
- }
- *ppp = package;
+ *nump = '\0';
- *pr = package;
- return 1;
-}
-
-static void generateNames(Spec s)
-{
- struct PackageRec *package;
- char buf[1024];
- char *name;
-
- package = s->packages;
- while (package) {
- if (package->subname) {
- sprintf(buf, "%s-%s", s->name, package->subname);
- name = buf;
- } else if (package->newname) {
- name = package->newname;
+ nump = buf;
+ SKIPSPACE(nump);
+ if (! *nump) {
+ num = 0;
} else {
- /* Must be the main package */
- name = s->name;
+ if (parseNum(buf, &num)) {
+ rpmError(RPMERR_BADSPEC, "line %d: Bad %s number: %s\n",
+ spec->lineNum, name, spec->line);
+ return RPMERR_BADSPEC;
+ }
}
- headerAddEntry(package->header, RPMTAG_NAME, RPM_STRING_TYPE, name, 1);
-
- package = package->next;
}
-}
-
-/* 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;
-}
-
-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);
+ /* Create the entry and link it in */
+ p = malloc(sizeof(struct Source));
+ p->num = num;
+ p->fullSource = strdup(field);
+ p->source = strrchr(p->fullSource, '/');
+ p->flags = flag;
+ if (p->source) {
+ p->source++;
} else {
- headerAddEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE,
- &time, 1);
- headerAddEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE,
- &name, 1);
- headerAddEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE,
- &text, 1);
- }
-}
-
-static int addChangelog(Header h, StringBuf sb)
-{
- char *s;
- int i;
- int time, lastTime = 0;
- char *date, *name, *text, *next;
-
- s = getStringBuf(sb);
-
- /* skip space */
- while (*s && isspace(*s)) s++;
-
- while (*s) {
- if (*s != '*') {
- rpmError(RPMERR_BADSPEC, "%%changelog entries must start with *");
- return RPMERR_BADSPEC;
- }
-
- /* find end of line */
- date = s;
- while (*s && *s != '\n') s++;
- if (! *s) {
- rpmError(RPMERR_BADSPEC, "incomplete %%changelog entry");
- return RPMERR_BADSPEC;
- }
- *s = '\0';
- text = s + 1;
-
- /* 4 fields of date */
- date++;
- s = date;
- for (i = 0; i < 4; i++) {
- while (*s && isspace(*s)) s++;
- while (*s && !isspace(*s)) s++;
- }
- while (isspace(*date)) date++;
- if (dateToTimet(date, (time_t *)&time)) {
- rpmError(RPMERR_BADSPEC, "bad date in %%changelog: %s", date);
- return RPMERR_BADSPEC;
- }
- if (lastTime && lastTime < time) {
- rpmError(RPMERR_BADSPEC,
- "%%changelog not in decending chronological order");
- return RPMERR_BADSPEC;
- }
- lastTime = time;
-
- /* skip space to the name */
- while (*s && isspace(*s)) s++;
- if (! *s) {
- rpmError(RPMERR_BADSPEC, "missing name in %%changelog");
- return RPMERR_BADSPEC;
- }
-
- /* name */
- name = s;
- while (*s) s++;
- while (s > name && isspace(*s)) {
- *s-- = '\0';
- }
- if (s == name) {
- rpmError(RPMERR_BADSPEC, "missing name in %%changelog");
- return RPMERR_BADSPEC;
- }
-
- /* text */
- while (*text && isspace(*text)) text++;
- if (! *text) {
- rpmError(RPMERR_BADSPEC, "no description in %%changelog");
- return RPMERR_BADSPEC;
- }
-
- /* find the next leading '*' (or eos) */
- s = text;
- do {
- 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;
+ p->source = p->fullSource;
}
- return 0;
-}
-
-/**********************************************************************/
-/* */
-/* Line reading */
-/* */
-/**********************************************************************/
-
-static int match_arch(char *s)
-{
- char *tok, *arch;
- int sense, match;
-
- rpmGetArchInfo(&arch, NULL);
- match = 0;
-
- tok = strtok(s, " \n\t");
- sense = (! strcmp(tok, "%ifarch")) ? 1 : 0;
-
- while ((tok = strtok(NULL, " \n\t"))) {
- if (! strcmp(tok, arch)) {
- match |= 1;
- }
+ if (tag != RPMTAG_ICON) {
+ p->next = spec->sources;
+ spec->sources = p;
+ } else {
+ p->next = pkg->icon;
+ pkg->icon = p;
}
- return (sense == match);
-}
-
-static int match_os(char *s)
-{
- char *tok, *os;
- int sense, match;
-
- rpmGetOsInfo(&os, NULL);
- match = 0;
-
- tok = strtok(s, " \n\t");
- sense = (! strcmp(tok, "%ifos")) ? 1 : 0;
+ spec->numSources++;
- while ((tok = strtok(NULL, " \n\t"))) {
- if (! strcmp(tok, os)) {
- match |= 1;
- }
+ if (tag != RPMTAG_ICON) {
+ sprintf(expansion, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), p->source);
+ sprintf(buf, "%s%d",
+ (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
+ addMacro(&spec->macros, buf, expansion);
+ sprintf(buf, "%sURL%d",
+ (flag & RPMBUILD_ISPATCH) ? "PATCH" : "SOURCE", num);
+ addMacro(&spec->macros, buf, p->fullSource);
}
-
- return (sense == match);
-}
-
-static struct read_level_entry {
- int reading; /* 1 if we are reading at this level */
- struct read_level_entry *next;
-} *read_level = NULL;
-
-static int read_line(FILE *f, char *line)
-{
- static struct read_level_entry *rl;
- int gotline;
- char *r;
- char *firstChar;
-
- do {
- gotline = 0;
- if (! fgets(line, LINE_BUF_SIZE, f)) {
- /* the end */
- if (read_level->next) {
- rpmError(RPMERR_UNMATCHEDIF, "Unclosed %%if");
- return RPMERR_UNMATCHEDIF;
- } else {
- return 0;
- }
- }
- firstChar = line;
- while (*firstChar && isspace(*firstChar)) {
- firstChar++;
- }
- if ((! strncmp("%ifarch", firstChar, 7)) ||
- (! strncmp("%ifnarch", firstChar, 8))) {
- expandMacros(line);
- rl = malloc(sizeof(struct read_level_entry));
- rl->next = read_level;
- rl->reading = read_level->reading && match_arch(line);
- read_level = rl;
- } else if ((! strncmp("%ifos", firstChar, 5)) ||
- (! strncmp("%ifnos", firstChar, 6))) {
- expandMacros(line);
- rl = malloc(sizeof(struct read_level_entry));
- rl->next = read_level;
- rl->reading = read_level->reading && match_os(line);
- read_level = rl;
- } else if (! strncmp("%else", firstChar, 5)) {
- expandMacros(line);
- if (! read_level->next) {
- /* Got an else with no %if ! */
- rpmError(RPMERR_UNMATCHEDIF, "Got a %%else with no if");
- return RPMERR_UNMATCHEDIF;
- }
- read_level->reading =
- read_level->next->reading && ! read_level->reading;
- } else if (! strncmp("%endif", firstChar, 6)) {
- expandMacros(line);
- if (! read_level->next) {
- rpmError(RPMERR_UNMATCHEDIF, "Got a %%endif with no if");
- return RPMERR_UNMATCHEDIF;
- }
- rl = read_level;
- read_level = rl->next;
- free(rl);
- } else {
- if (read_level->reading) {
- expandMacros(line);
- }
- gotline = 1;
- }
- } while (! (gotline && read_level->reading));
- r = line + (strlen(line)) - 1;
- while (isspace(*r)) {
- *(r--) = '\0';
- }
- return 1;
+ return 0;
}
-/**********************************************************************/
-/* */
-/* Line parsing */
-/* */
-/**********************************************************************/
-
-struct preamble_line {
- int tag;
- int len;
- char *token;
-} preamble_spec[] = {
- {RPMTAG_NAME, 0, "name"},
- {RPMTAG_VERSION, 0, "version"},
- {RPMTAG_RELEASE, 0, "release"},
- {RPMTAG_SERIAL, 0, "serial"},
- {RPMTAG_DESCRIPTION, 0, "description"},
- {RPMTAG_SUMMARY, 0, "summary"},
- {RPMTAG_COPYRIGHT, 0, "copyright"},
- {RPMTAG_COPYRIGHT, 0, "license"},
- {RPMTAG_DISTRIBUTION, 0, "distribution"},
- {RPMTAG_VENDOR, 0, "vendor"},
- {RPMTAG_GROUP, 0, "group"},
- {RPMTAG_PACKAGER, 0, "packager"},
- {RPMTAG_URL, 0, "url"},
- {RPMTAG_ROOT, 0, "root"},
- {RPMTAG_SOURCE, 0, "source"},
- {RPMTAG_PATCH, 0, "patch"},
- {RPMTAG_NOSOURCE, 0, "nosource"},
- {RPMTAG_NOPATCH, 0, "nopatch"},
- {RPMTAG_EXCLUDEARCH, 0, "excludearch"},
- {RPMTAG_EXCLUSIVEARCH, 0, "exclusivearch"},
- {RPMTAG_EXCLUDEOS, 0, "excludeos"},
- {RPMTAG_EXCLUSIVEOS, 0, "exclusiveos"},
- {RPMTAG_EXCLUDE, 0, "exclude"},
- {RPMTAG_EXCLUSIVE, 0, "exclusive"},
- {RPMTAG_ICON, 0, "icon"},
- {RPMTAG_PROVIDES, 0, "provides"},
- {RPMTAG_REQUIREFLAGS, 0, "requires"},
- {RPMTAG_PREREQ, 0, "prereq"},
- {RPMTAG_CONFLICTFLAGS, 0, "conflicts"},
- {RPMTAG_OBSOLETES, 0, "obsoletes"},
- {RPMTAG_DEFAULTPREFIX, 0, "prefix"},
- {RPMTAG_BUILDROOT, 0, "buildroot"},
- {RPMTAG_BUILDARCHS, 0, "buildarchitectures"},
- {RPMTAG_AUTOREQPROV, 0, "autoreqprov"},
- {0, 0, 0}
-};
-
-static int find_preamble_line(char *line, char **s)
+char *getSource(Spec spec, int num, int flag)
{
- struct preamble_line *p = preamble_spec;
-
- while (p->token && strncasecmp(line, p->token, p->len)) {
- p++;
- }
- if (!p->token) return 0;
- *s = line + p->len;
-
- /* Unless this is a source or a patch, a ':' better be next */
- if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) {
- *s += strspn(*s, " \t");
- if (**s != ':') {
- return 0;
- }
- }
-
- *s += strspn(*s, ": \t");
- return p->tag;
+ return getSourceAux(spec, num, flag, 0);
}
-/* None of these can be 0 !! */
-#define PREAMBLE_PART 1
-#define PREP_PART 2
-#define BUILD_PART 3
-#define INSTALL_PART 4
-#define CLEAN_PART 5
-#define PREIN_PART 6
-#define POSTIN_PART 7
-#define PREUN_PART 8
-#define POSTUN_PART 9
-#define FILES_PART 10
-#define CHANGELOG_PART 11
-#define DESCRIPTION_PART 12
-#define TRIGGERIN_PART 13
-#define TRIGGERUN_PART 14
-#define VERIFYSCRIPT_PART 15
-
-static struct part_rec {
- int part;
- int len;
- char *s;
-} part_list[] = {
- {PREAMBLE_PART, 0, "%package"},
- {PREP_PART, 0, "%prep"},
- {BUILD_PART, 0, "%build"},
- {INSTALL_PART, 0, "%install"},
- {CLEAN_PART, 0, "%clean"},
- {PREUN_PART, 0, "%preun"},
- {POSTUN_PART, 0, "%postun"},
- {PREIN_PART, 0, "%pre"},
- {POSTIN_PART, 0, "%post"},
- {FILES_PART, 0, "%files"},
- {CHANGELOG_PART, 0, "%changelog"},
- {DESCRIPTION_PART, 0, "%description"},
- {TRIGGERUN_PART, 0, "%triggerun"},
- {TRIGGERIN_PART, 0, "%trigger"},
- {VERIFYSCRIPT_PART, 0, "%verifyscript"},
- {0, 0, 0}
-};
-
-static int check_part(char *line, char **s)
+char *getFullSource(Spec spec, int num, int flag)
{
- struct part_rec *p = part_list;
-
- while (p->s && strncmp(line, p->s, p->len)) {
- p++;
- }
- if (!p) return 0;
- *s = line + p->len;
- *s += strspn(*s, " \t");
- if (**s == '\0') {
- *s = NULL;
- }
- return p->part;
+ return getSourceAux(spec, num, flag, 1);
}
-#if 0
-static char *chop_line(char *s)
+static char *getSourceAux(Spec spec, int num, int flag, int full)
{
- char *p, *e;
-
- p = s;
- p += strspn(s, " \t");
- if (*p == '\0') {
- return NULL;
- }
- e = s + strlen(s) - 1;
- while (index(" \t", *e)) {
- e--;
- }
- return p;
-}
-#endif
+ struct Source *p = spec->sources;
-static void addListEntry(Header h, int_32 tag, char *line)
-{
- int argc;
- char **argv;
- char **argvs;
- char *s;
+ p = findSource(spec, num, flag);
- argvs = argv = malloc(strlen(line) * sizeof(char *));
- argc = 0;
- while ((s = strtok(line, " \t"))) {
- *argv = s;
- argc++;
- argv++;
- line = NULL;
- }
- if (argc) {
- headerAddEntry(h, tag, RPM_STRING_ARRAY_TYPE, argvs, argc);
- }
- free(argvs);
+ return (p) ? (full ? p->fullSource : p->source) : NULL;
}
-static int finishCurrentPart(Spec spec, StringBuf sb,
- struct PackageRec *cur_package,
- int cur_part, char *triggerArgs,
- char *scriptProg)
+static struct Source *findSource(Spec spec, int num, int flag)
{
- int t1 = 0;
- int t2 = 0;
-
- stripTrailingBlanksStringBuf(sb);
-
- switch (cur_part) {
- case PREIN_PART:
- t1 = RPMTAG_PREIN;
- t2 = RPMTAG_PREINPROG;
- break;
- case POSTIN_PART:
- t1 = RPMTAG_POSTIN;
- t2 = RPMTAG_POSTINPROG;
- break;
- case PREUN_PART:
- t1 = RPMTAG_PREUN;
- t2 = RPMTAG_PREUNPROG;
- break;
- case POSTUN_PART:
- t1 = RPMTAG_POSTUN;
- t2 = RPMTAG_POSTUNPROG;
- break;
- case VERIFYSCRIPT_PART:
- t1 = RPMTAG_VERIFYSCRIPT;
- break;
- case DESCRIPTION_PART:
- t1 = RPMTAG_DESCRIPTION;
- break;
- case CHANGELOG_PART:
- /* %changelog is a little special. It goes in the */
- /* "main" package no matter where it appears, and it */
- /* ends up in all the packages. */
- if (addChangelog(spec->packages->header, sb)) {
- return 1;
- }
- break;
- case TRIGGERIN_PART:
- if (addTrigger(cur_package, RPMSENSE_TRIGGER_IN,
- getStringBuf(sb), triggerArgs)) {
- return 1;
- }
- break;
- case TRIGGERUN_PART:
- if (addTrigger(cur_package, RPMSENSE_TRIGGER_UN,
- getStringBuf(sb), triggerArgs)) {
- return 1;
- }
- break;
- }
- if (t1 && (*(getStringBuf(sb)) != '\0')) {
- headerAddEntry(cur_package->header, t1,
- RPM_STRING_TYPE, getStringBuf(sb), 1);
- }
- if (t2) {
- addReqProv(cur_package, RPMSENSE_PREREQ, scriptProg, NULL);
- headerAddEntry(cur_package->header, t2,
- RPM_STRING_TYPE, scriptProg, 1);
- }
- return 0;
-}
+ struct Source *p = spec->sources;
-/**********************************************************************/
-/* */
-/* Main specfile parsing routine */
-/* */
-/**********************************************************************/
-
-Spec *parseSpec(FILE *f, char *specfile, char *buildRootOverride)
-{
- Spec *res;
- Spec s;
- char **archs = NULL;
- char **arch;
- int i, count;
-
- s = parseSpecAux(f, specfile, buildRootOverride, &archs);
-
- if (s) {
- /* No BuildArchitectures field */
- res = (Spec *) malloc(2 * sizeof(Spec));
- res[0] = s;
- res[1] = NULL;
- return res;
- }
-
- if (! archs) {
- /* Error */
- return NULL;
- }
-
- /* We have a BuildArchitectures field */
- count = 0;
- while (archs[count]) {
- count++;
- }
- res = (Spec *) malloc(count * sizeof(Spec));
-
- i = 0;
- arch = archs;
- while (*arch) {
- if (rpmMachineScore(RPM_MACHTABLE_BUILDARCH, *arch)) {
- rewind(f);
- rpmSetMachine(*arch, NULL);
- res[i] = parseSpecAux(f, specfile, buildRootOverride, NULL);
- if (! res[i]) {
- /* Error */
- freeSplitString(archs);
- while (i) {
- i--;
- freeSpec(res[i]);
- }
- free(res);
- return NULL;
- }
- headerAddEntry(res[i]->packages->header, RPMTAG_BUILDARCHS,
- RPM_STRING_ARRAY_TYPE, archs, count);
- res[i]->buildArch = strdup(*arch);
- i++;
+ while (p) {
+ if ((num == p->num) && (p->flags & flag)) {
+ return p;
}
- arch++;
+ p = p->next;
}
- res[i] = NULL;
- freeSplitString(archs);
-
- return res;
+ return NULL;
}
-Spec parseSpecAux(FILE *f, char *specfile, char *buildRootOverride,
- char ***buildArchs)
+void freeSources(Spec spec)
{
- char buf[LINE_BUF_SIZE]; /* read buffer */
- char buf2[LINE_BUF_SIZE];
- char fileFile[LINE_BUF_SIZE];
- char scriptProg[LINE_BUF_SIZE];
- char triggerArgs[LINE_BUF_SIZE];
- char *line; /* "parsed" read buffer */
-
- int x, serial, tag, cur_part;
- int lookupopts;
- StringBuf sb;
- char *s = NULL;
- char *s1, *s2;
- int gotBuildroot = 0;
- int gotRoot = 0;
- int versionMacroSet = 0;
- int releaseMacroSet = 0;
- char *arch, *os;
-
- struct PackageRec *cur_package = NULL;
- Spec spec = (struct SpecRec *) malloc(sizeof(struct SpecRec));
-
- spec->name = NULL;
- spec->specfile = strdup(specfile);
- spec->numSources = 0;
- spec->numPatches = 0;
- spec->sources = NULL;
- spec->prep = newStringBuf();
- spec->build = newStringBuf();
- spec->install = newStringBuf();
- spec->doc = newStringBuf();
- spec->clean = newStringBuf();
- spec->packages = NULL;
- spec->noSource = NULL;
- spec->noPatch = NULL;
- spec->numNoSource = 0;
- spec->numNoPatch = 0;
- spec->buildroot = NULL;
- spec->autoReqProv = 1;
- spec->buildArch = NULL;
-
- sb = newStringBuf();
- reset_spec(); /* Reset the parser */
+ struct Source *p1, *p2;
- rpmGetArchInfo(&arch, NULL);
- rpmGetOsInfo(&os, NULL);
- addMacro("buildarch", arch);
- addMacro("buildos", os);
-
- scriptProg[0] = '\0';
- cur_part = PREAMBLE_PART;
- while ((x = read_line(f, buf)) > 0) {
- line = buf;
- s = NULL;
- if ((tag = check_part(line, &s))) {
- rpmMessage(RPMMESS_DEBUG, "Switching to part: %d\n", tag);
- if (finishCurrentPart(spec, sb, cur_package,
- cur_part, triggerArgs, scriptProg)) {
- return NULL;
- }
- cur_part = tag;
- truncStringBuf(sb);
-
- /* Now switch the current package to s */
- if (s) {
- switch (tag) {
- case PREP_PART:
- case BUILD_PART:
- case INSTALL_PART:
- case CLEAN_PART:
- case CHANGELOG_PART:
- rpmError(RPMERR_BADARG, "Tag takes no arguments: %s", s);
- return NULL;
- }
- }
-
- /* Rip through s for -f in %files */
- /* not only is this code disgusting, but it allows -f on any tag */
- fileFile[0] = '\0';
- s1 = NULL;
- if (s &&
- ((s1 = strstr(s, " -f ")) ||
- (!strncmp(s, "-f ", 3)))) {
- if (s1) {
- s1[0] = ' ';
- s1++;
- } else {
- s1 = s;
- }
- s1[0] = ' '; s1[1] = ' '; s1[2] = ' ';
- s1 += 3;
- while (isspace(*s1)) {
- s1++;
- }
-
- s2 = fileFile;
- while (*s1 && !isspace(*s1)) {
- *s2 = *s1;
- *s1 = ' ';
- s1++;
- s2++;
- }
- *s2 = '\0';
- while (isspace(*s)) {
- s++;
- }
- if (! *s) {
- s = NULL;
- }
- }
-
- rpmMessage(RPMMESS_DEBUG, "fileFile = %s\n",
- fileFile[0] ? fileFile : "(null)");
-
- /* If trigger, pull off the args */
- if (tag == TRIGGERIN_PART || tag == TRIGGERUN_PART) {
- s1 = strstr(s, "--");
- if (s1) {
- strcpy(triggerArgs, s1+2);
- *s1 = '\0';
- s = strtok(s, " \n\t");
- } else {
- strcpy(triggerArgs, s);
- s = NULL;
- }
- }
-
- /* find possible -p <prog> */
- if ((tag == PREIN_PART) ||
- (tag == POSTIN_PART) ||
- (tag == PREUN_PART) ||
- (tag == POSTUN_PART)) {
-
- scriptProg[0] = '\0';
- s1 = NULL;
-
- if (s &&
- ((s1 = strstr(s, " -p ")) ||
- (!strncmp(s, "-p ", 3)))) {
-
- if (s1) {
- s1[0] = ' ';
- s1++;
- } else {
- s1 = s;
- }
- s1[0] = ' '; s1[1] = ' '; s1[2] = ' ';
- s1 += 3;
- while (isspace(*s1)) {
- s1++;
- }
-
- s2 = scriptProg;
- while (*s1 && !isspace(*s1)) {
- *s2 = *s1;
- *s1 = ' ';
- s1++;
- s2++;
- }
-
- *s2 = '\0';
- while (isspace(*s)) {
- s++;
- }
- if (! *s) {
- s = NULL;
- }
- }
-
- /* defaults to /bin/sh */
- if (! scriptProg[0]) {
- strcpy(scriptProg, "/bin/sh");
- } else {
- if (scriptProg[0] != '/') {
- rpmError(RPMERR_BADSPEC, "pre/post -p arg must begin with \'/\': %s", scriptProg);
- return NULL;
- }
- }
- rpmMessage(RPMMESS_DEBUG, "scriptProg = %s\n", scriptProg);
- }
-
- /* At this point s is the remaining args, which can only */
- /* be -n <pkg>, or simply <pkg>. */
-
- /* Handle -n in part tags */
- lookupopts = 0;
- if (s) {
- if (!strncmp(s, "-n", 2)) {
- s += 2;
- s += strspn(s, ": \t");
- if (*s == '\0') {
- rpmError(RPMERR_BADARG, "-n takes argument");
- return NULL;
- }
- lookupopts = LP_NEWNAME;
- } else {
- lookupopts = LP_SUBNAME;
- }
- /* Handle trailing whitespace */
- s1 = s + strlen(s) - 1;
- while (*s1 == ' ' || *s1 == '\n' || *s1 == '\t') {
- s1--;
- }
- s1++;
- *s1 = '\0';
- }
-
- switch (tag) {
- case PREP_PART:
- case BUILD_PART:
- case INSTALL_PART:
- case CLEAN_PART:
- case CHANGELOG_PART:
- /* Do not switch parts for these */
- break;
- case PREAMBLE_PART:
- lookupopts |= LP_CREATE | LP_FAIL_EXISTS;
- /* Fall through */
- default:
- /* XXX - should be able to drop the -n in non-%package parts */
- if (! lookup_package(spec, &cur_package, s, lookupopts)) {
- rpmError(RPMERR_INTERNAL, "Package lookup failed: %s",
- (s) ? s : "(main)");
- return NULL;
- }
- rpmMessage(RPMMESS_DEBUG, "Switched to package: %s\n",
- s ? s : "(main)");
- }
-
- if (cur_part == FILES_PART) {
- /* set files to 0 (current -1 means no %files, no package */
- cur_package->files = 0;
- if (fileFile[0]) {
- cur_package->fileFile = strdup(fileFile);
- }
- }
-
- /* This line has no content -- it was just a control line */
- continue;
- }
-
- /* Check for implicit "base" package. */
- /* That means that the specfile does not start with %package */
- if (! cur_package) {
- lookupopts = 0;
- if (cur_part == PREAMBLE_PART) {
- lookupopts = LP_CREATE | LP_FAIL_EXISTS;
- }
- if (! lookup_package(spec, &cur_package, NULL, lookupopts)) {
- rpmError(RPMERR_INTERNAL, "Base package lookup failed!");
- return NULL;
- }
- rpmMessage(RPMMESS_DEBUG, "Switched to BASE package\n");
- }
-
- switch (cur_part) {
- case PREAMBLE_PART:
- if ((tag = find_preamble_line(line, &s))) {
- switch (tag) {
- case RPMTAG_EXCLUDE:
- case RPMTAG_EXCLUSIVE:
- rpmMessage(RPMMESS_WARNING,
- "Exclude/Exclusive are depricated.\n"
- "Use ExcludeArch/ExclusiveArch instead.\n");
- sprintf(buf2, "%s %s",
- (tag == RPMTAG_EXCLUDE) ? "%ifarch" : "%ifnarch",
- s);
- if (match_arch(buf2)) {
- rpmError(RPMERR_BADARCH, "Arch mismatch!");
- return NULL;
- }
- addListEntry(cur_package->header,
- (tag == RPMTAG_EXCLUDE) ?
- RPMTAG_EXCLUDEARCH : RPMTAG_EXCLUSIVEARCH,
- s);
- break;
- case RPMTAG_EXCLUDEARCH:
- case RPMTAG_EXCLUSIVEARCH:
- sprintf(buf2, "%s %s", (tag == RPMTAG_EXCLUDEARCH) ?
- "%ifarch" : "%ifnarch", s);
- if (match_arch(buf2)) {
- rpmError(RPMERR_BADARCH, "Arch mismatch!");
- return NULL;
- }
- addListEntry(cur_package->header, tag, s);
- break;
- case RPMTAG_EXCLUDEOS:
- case RPMTAG_EXCLUSIVEOS:
- sprintf(buf2, "%s %s", (tag == RPMTAG_EXCLUDEOS) ?
- "%ifos" : "%ifnos", s);
- if (match_os(buf2)) {
- rpmError(RPMERR_BADOS, "OS mismatch!");
- return NULL;
- }
- addListEntry(cur_package->header, tag, s);
- break;
- case RPMTAG_NAME:
- s1 = s;
- while (*s1 && *s1 != ' ' && *s1 != '\t') s1++;
- *s1 = '\0';
- if (!spec->name) {
- spec->name = strdup(s);
- }
- /* The NAME entries must be generated after */
- /* the whole spec file is parsed. */
- break;
- case RPMTAG_VERSION:
- case RPMTAG_RELEASE:
- s1 = s;
- while (*s1 && *s1 != ' ' && *s1 != '\t') s1++;
- *s1 = '\0';
- if (s1 == s) {
- rpmError(RPMERR_BADSPEC, (tag == RPMTAG_VERSION) ?
- "Empty version field." :
- "Empty release field.");
- return NULL;
- }
- if (tag == RPMTAG_VERSION) {
- if (! versionMacroSet) {
- versionMacroSet = 1;
- addMacro("PACKAGE_VERSION", s);
- }
- } else {
- if (! releaseMacroSet) {
- releaseMacroSet = 1;
- addMacro("PACKAGE_RELEASE", s);
- }
- }
- case RPMTAG_SUMMARY:
- case RPMTAG_DISTRIBUTION:
- case RPMTAG_VENDOR:
- case RPMTAG_COPYRIGHT:
- case RPMTAG_PACKAGER:
- case RPMTAG_GROUP:
- case RPMTAG_URL:
- headerAddEntry(cur_package->header, tag, RPM_STRING_TYPE, s, 1);
- break;
- case RPMTAG_BUILDARCHS:
- if (buildArchs) {
- *buildArchs = splitString(s, strlen(s), ' ');
- freeSpec(spec);
- freeStringBuf(sb);
- return NULL;
- }
- break;
- case RPMTAG_BUILDROOT:
- gotBuildroot = 1;
- spec->buildroot = strdup(s);
- break;
- case RPMTAG_DEFAULTPREFIX:
- headerAddEntry(cur_package->header, tag, RPM_STRING_TYPE, s, 1);
- break;
- case RPMTAG_SERIAL:
- serial = atoi(s);
- headerAddEntry(cur_package->header, tag, RPM_INT32_TYPE, &serial, 1);
- break;
- case RPMTAG_DESCRIPTION:
- /* Special case -- need to handle backslash */
- truncStringBuf(sb);
- while (1) {
- s1 = s + strlen(s) - 1;
- if (*s1 != '\\') {
- break;
- }
- *s1 = '\0';
- appendLineStringBuf(sb, s);
- read_line(f, buf);
- s = buf;
- }
- appendStringBuf(sb, s);
- headerAddEntry(cur_package->header, RPMTAG_DESCRIPTION,
- RPM_STRING_TYPE, getStringBuf(sb), 1);
- break;
- case RPMTAG_ROOT:
- /* special case */
- gotRoot = 1;
- rpmMessage(RPMMESS_DEBUG, "Got root: %s\n", s);
- rpmMessage(RPMMESS_WARNING, "The Root: tag is depricated. Use Buildroot: instead\n");
- rpmSetVar(RPMVAR_ROOT, s);
- break;
- case RPMTAG_ICON:
- cur_package->icon = strdup(s);
- break;
- case RPMTAG_NOPATCH:
- case RPMTAG_NOSOURCE:
- if (noSourcePatch(spec, s, tag)) {
- return NULL;
- }
- break;
- case RPMTAG_SOURCE:
- case RPMTAG_PATCH:
- if (addSource(spec, line)) {
- return NULL;
- }
- break;
- case RPMTAG_OBSOLETES:
- case RPMTAG_PROVIDES:
- if (parseProvides(cur_package, s, tag)) {
- return NULL;
- }
- break;
- case RPMTAG_REQUIREFLAGS:
- case RPMTAG_CONFLICTFLAGS:
- case RPMTAG_PREREQ:
- if (parseRequiresConflicts(cur_package, s, tag)) {
- return NULL;
- }
- break;
- case RPMTAG_AUTOREQPROV:
- s1 = strtok(s, " \t\n");
- if (!s1) {
- spec->autoReqProv = 0;
- } else if (s1[0] == 'n' || s1[0] == 'N') {
- spec->autoReqProv = 0;
- } else if (!strcasecmp(s1, "false")) {
- spec->autoReqProv = 0;
- } else if (!strcasecmp(s1, "off")) {
- spec->autoReqProv = 0;
- } else if (!strcmp(s1, "0")) {
- spec->autoReqProv = 0;
- }
- break;
- default:
- /* rpmMessage(RPMMESS_DEBUG, "Skipping: %s\n", line); */
- /* This shouldn't happen? */
- rpmError(RPMERR_INTERNAL, "Bogus token");
- return NULL;
- }
- } else {
- /* Not a recognized preamble part */
- s1 = line;
- while (*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
- /* Handle blanks lines and comments */
- if (*s1 && (*s1 != '#')) {
- /*rpmMessage(RPMMESS_WARNING, "Unknown Field: %s\n", line);*/
- rpmError(RPMERR_BADSPEC, "Unknown Field: %s\n", line);
- return NULL;
- }
- }
- break;
- case PREP_PART:
- appendLineStringBuf(spec->prep, line);
- break;
- case BUILD_PART:
- appendLineStringBuf(spec->build, line);
- break;
- case INSTALL_PART:
- appendLineStringBuf(spec->install, line);
- break;
- case CLEAN_PART:
- appendLineStringBuf(spec->clean, line);
- break;
- case DESCRIPTION_PART:
- case CHANGELOG_PART:
- case PREIN_PART:
- case POSTIN_PART:
- case PREUN_PART:
- case POSTUN_PART:
- case VERIFYSCRIPT_PART:
- appendLineStringBuf(sb, line);
- break;
- case TRIGGERIN_PART:
- case TRIGGERUN_PART:
- appendLineStringBuf(sb, line);
- break;
- case FILES_PART:
- s1 = line;
- while (*s1 && (*s1 == ' ' || *s1 == '\t')) s1++;
- /* Handle blanks lines and comments */
- if (*s1 && (*s1 != '#')) {
- cur_package->files++;
- appendLineStringBuf(cur_package->filelist, line);
- }
- break;
- default:
- rpmError(RPMERR_INTERNAL, "Bad part");
- return NULL;
- } /* switch */
- }
- if (x < 0) {
- return NULL;
- }
-
- /* finish current part */
- if (finishCurrentPart(spec, sb, cur_package,
- cur_part, triggerArgs,
- scriptProg)) {
- return NULL;
- }
-
- freeStringBuf(sb);
-
- if (gotRoot && gotBuildroot) {
- freeSpec(spec);
- rpmError(RPMERR_BADSPEC,
- "Spec file can not have both Root: and Buildroot:");
- return NULL;
- }
- if (spec->buildroot) {
- /* This package can do build roots */
- if (buildRootOverride) {
- rpmSetVar(RPMVAR_ROOT, buildRootOverride);
- rpmSetVar(RPMVAR_BUILDROOT, buildRootOverride);
- } else {
- if ((s = rpmGetVar(RPMVAR_BUILDROOT))) {
- /* Take build prefix from rpmrc */
- rpmSetVar(RPMVAR_ROOT, s);
- } else {
- /* Use default */
- rpmSetVar(RPMVAR_ROOT, spec->buildroot);
- rpmSetVar(RPMVAR_BUILDROOT, spec->buildroot);
- }
- }
- } else {
- /* Package can not do build prefixes */
- if (buildRootOverride) {
- freeSpec(spec);
- rpmError(RPMERR_BADARG, "Package can not do build prefixes");
- return NULL;
- }
+ p1 = spec->sources;
+ while (p1) {
+ p2 = p1;
+ p1 = p1->next;
+ FREE(p2->fullSource);
+ free(p2);
}
-
- generateNames(spec);
- return spec;
}
-/**********************************************************************/
-/* */
-/* Resets the parser */
-/* */
-/**********************************************************************/
-
-static void reset_spec()
+int parseNoSource(Spec spec, char *field, int tag)
{
- static done = 0;
- struct read_level_entry *rl;
- struct preamble_line *p = preamble_spec;
- struct part_rec *p1 = part_list;
-
- rpmSetVar(RPMVAR_ROOT, NULL);
-
- while (read_level) {
- rl = read_level;
- read_level = read_level->next;
- free(rl);
+ char buf[BUFSIZ];
+ char *s, *name;
+ int num, flag;
+ struct Source *p;
+
+ if (tag == RPMTAG_NOSOURCE) {
+ flag = RPMBUILD_ISSOURCE;
+ name = "source";
+ } else {
+ flag = RPMBUILD_ISPATCH;
+ name = "patch";
}
- read_level = malloc(sizeof(struct read_level_entry));
- read_level->next = NULL;
- read_level->reading = 1;
-
- resetMacros();
- if (! done) {
- /* Put one time only things in here */
- while (p->tag) {
- p->len = strlen(p->token);
- p++;
- }
- while (p1->part) {
- p1->len = strlen(p1->s);
- p1++;
+ strcpy(buf, field);
+ field = buf;
+ while ((s = strtok(field, ", \t"))) {
+ if (parseNum(s, &num)) {
+ rpmError(RPMERR_BADSPEC, "line %d: Bad number: %s",
+ spec->lineNum, spec->line);
+ return RPMERR_BADSPEC;
}
- done = 1;
- }
-}
-
-/**********************************************************************/
-/* */
-/* Spec struct dumping (for debugging) */
-/* */
-/**********************************************************************/
+ if (! (p = findSource(spec, num, flag))) {
+ rpmError(RPMERR_BADSPEC, "line %d: Bad no%s number: %d",
+ spec->lineNum, name, num);
+ return RPMERR_BADSPEC;
+ }
-void dumpSpec(Spec s, FILE *f)
-{
- struct PackageRec *p;
-
- fprintf(f, "########################################################\n");
- fprintf(f, "SPEC NAME = (%s)\n", s->name);
- fprintf(f, "PREP =v\n");
- fprintf(f, "%s", getStringBuf(s->prep));
- fprintf(f, "PREP =^\n");
- fprintf(f, "BUILD =v\n");
- fprintf(f, "%s", getStringBuf(s->build));
- fprintf(f, "BUILD =^\n");
- fprintf(f, "INSTALL =v\n");
- fprintf(f, "%s", getStringBuf(s->install));
- fprintf(f, "INSTALL =^\n");
- fprintf(f, "CLEAN =v\n");
- fprintf(f, "%s", getStringBuf(s->clean));
- fprintf(f, "CLEAN =^\n");
+ p->flags |= RPMBUILD_ISNO;
- p = s->packages;
- while (p) {
- dumpPackage(p, f);
- p = p->next;
+ field = NULL;
}
-}
-
-static void dumpPackage(struct PackageRec *p, FILE *f)
-{
- fprintf(f, "_________________________________________________________\n");
- fprintf(f, "SUBNAME = (%s)\n", p->subname);
- fprintf(f, "NEWNAME = (%s)\n", p->newname);
- fprintf(f, "FILES = %d\n", p->files);
- fprintf(f, "FILES =v\n");
- fprintf(f, "%s", getStringBuf(p->filelist));
- fprintf(f, "FILES =^\n");
- fprintf(f, "HEADER =v\n");
- headerDump(p->header, f, 1, rpmTagTable);
- fprintf(f, "HEADER =^\n");
+ return 0;
}
diff --git a/build/spec.h b/build/spec.h
index d6d967c0e..28d73697a 100644
--- a/build/spec.h
+++ b/build/spec.h
@@ -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"
+
+#if 0
+struct ReqProvTrigger {
+ int flags;
+ char *name;
+ char *version;
+ int index; /* Only used for triggers */
+ struct ReqProvTrigger *next;
+};
+#endif
+
+#define RPMBUILD_ISSOURCE 1
+#define RPMBUILD_ISPATCH (1 << 1)
+#define RPMBUILD_ISICON (1 << 2)
+#define RPMBUILD_ISNO (1 << 3)
+
+#define RPMBUILD_DEFAULT_LANG "C"
+
+struct Source {
+ char *fullSource;
+ char *source; /* Pointer into fullSource */
+ int flags;
+ int num;
+ struct Source *next;
+};
+
+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;
-typedef struct SpecRec *Spec;
+ StringBuf specialDoc;
+
+#if 0
+ struct ReqProvTrigger *triggers;
+ char *triggerScripts;
+#endif
+
+ char *fileFile;
+ StringBuf fileList; /* If NULL, package will not be written */
-Spec *parseSpec(FILE *f, char *specfile, char *buildRootOverride);
-void freeSpec(Spec s);
+ struct PackageStruct *next;
+};
-void dumpSpec(Spec s, FILE *f);
+typedef struct SpecStruct *Spec;
+typedef struct PackageStruct *Package;
-char *getSource(Spec s, int ispatch, int num);
-char *getFullSource(Spec s, int ispatch, int num);
+Spec newSpec(void);
+void freeSpec(Spec spec);
-int verifySpec(Spec s);
+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_
diff --git a/build/specP.h b/build/specP.h
deleted file mode 100644
index a90ed7f41..000000000
--- a/build/specP.h
+++ /dev/null
@@ -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_
diff --git a/build/trigger.h b/build/trigger.h
deleted file mode 100644
index 00fc483f4..000000000
--- a/build/trigger.h
+++ /dev/null
@@ -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_
diff --git a/build/vspec.c b/build/vspec.c
deleted file mode 100644
index cc3f35510..000000000
--- a/build/vspec.c
+++ /dev/null
@@ -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;
-}
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 4f2999e90..c24fe493e 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -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))
diff --git a/lib/misc.c b/lib/misc.c
index 0f65333cc..7127b5ed0 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -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;
diff --git a/rpm.c b/rpm.c
index febd7049b..098c78697 100755
--- a/rpm.c
+++ b/rpm.c
@@ -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;
diff --git a/rpm.spec b/rpm.spec
index 854234bc7..014eecf0a 100644
--- a/rpm.spec
+++ b/rpm.spec
@@ -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