merged in Marc's new build code
CVS patchset: 1956 CVS date: 1998/01/12 21:31:29
This commit is contained in:
parent
ec07f9df95
commit
757e50ffc8
31
CHANGES
31
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
|
||||
|
|
13
Makefile.in
13
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
|
||||
|
|
|
@ -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@
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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"
|
||||
_("...")
|
941
build/build.c
941
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 "spec.h"
|
||||
#include "specP.h"
|
||||
#include "rpmlib.h"
|
||||
#include "messages.h"
|
||||
#include "stringbuf.h"
|
||||
#include "misc.h"
|
||||
#include "spec.h"
|
||||
#include "build.h"
|
||||
#include "lib/misc.h"
|
||||
#include "lib/messages.h"
|
||||
#include "rpmlib.h"
|
||||
#include "pack.h"
|
||||
#include "popt/popt.h"
|
||||
#include "config.h"
|
||||
#include "files.h"
|
||||
|
||||
#include "names.h"
|
||||
static void doRmSource(Spec spec);
|
||||
static int writeVars(Spec spec, FILE *f);
|
||||
|
||||
struct Script {
|
||||
char *name;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
struct Script *openScript(Spec spec, int builddir, char *name);
|
||||
void writeScript(struct Script *script, char *s);
|
||||
int execScript(struct Script *script);
|
||||
void freeScript(struct Script *script, int test);
|
||||
int execPart(Spec s, char *sb, char *name, int builddir, int test);
|
||||
static int doSetupMacro(Spec spec, StringBuf sb, char *line);
|
||||
static int doPatchMacro(Spec spec, StringBuf sb, char *line);
|
||||
static char *do_untar(Spec spec, int c, int quietly);
|
||||
static char *do_patch(Spec spec, int c, int strip, char *dashb,
|
||||
int reverse, int removeEmpties);
|
||||
int isCompressed(char *file);
|
||||
static void doSweep(Spec s);
|
||||
static int doRmSource(Spec s);
|
||||
|
||||
char build_subdir[1024];
|
||||
|
||||
struct Script *openScript(Spec spec, int builddir, char *name)
|
||||
int buildSpec(Spec spec, int what, int test)
|
||||
{
|
||||
int x, rc;
|
||||
|
||||
if (!spec->inBuildArchitectures && spec->buildArchitectureCount) {
|
||||
/* When iterating over buildArchitectures, do the source */
|
||||
/* packaging on the first run, and skip RMSOURCE altogether */
|
||||
x = 0;
|
||||
while (x < spec->buildArchitectureCount) {
|
||||
if ((rc = buildSpec(spec->buildArchitectureSpecs[x],
|
||||
(what & ~RPMBUILD_RMSOURCE) |
|
||||
(x ? 0 : (what & RPMBUILD_PACKAGESOURCE)),
|
||||
test))) {
|
||||
return rc;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
} else {
|
||||
if (what & RPMBUILD_PREP) {
|
||||
if ((rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if (what & RPMBUILD_BUILD) {
|
||||
if ((rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if (what & RPMBUILD_INSTALL) {
|
||||
if ((rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (what & RPMBUILD_PACKAGESOURCE) {
|
||||
if ((rc = processSourceFiles(spec))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if ((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
|
||||
(what & RPMBUILD_FILECHECK)) {
|
||||
if ((rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (what & RPMBUILD_PACKAGESOURCE) {
|
||||
if ((rc = packageSources(spec))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if (what & RPMBUILD_PACKAGEBINARY) {
|
||||
if ((rc = packageBinaries(spec))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (what & RPMBUILD_CLEAN) {
|
||||
if ((rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if (what & RPMBUILD_RMBUILD) {
|
||||
if ((rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (what & RPMBUILD_RMSOURCE) {
|
||||
doRmSource(spec);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int doScript(Spec spec, int what, char *name, StringBuf sb, int test)
|
||||
{
|
||||
struct Script *script = malloc(sizeof(struct Script));
|
||||
struct PackageRec *main_package = spec->packages;
|
||||
char *s, * arch, * os;
|
||||
int fd;
|
||||
int_32 foo;
|
||||
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;
|
||||
}
|
||||
|
||||
if (makeTempFile(NULL, &scriptName, &fd)) {
|
||||
rpmError(RPMERR_SCRIPT, "Unable to open temp file");
|
||||
return RPMERR_SCRIPT;
|
||||
}
|
||||
f = fdopen(fd, "w");
|
||||
|
||||
if (writeVars(spec, f)) {
|
||||
fclose(f);
|
||||
FREE(scriptName);
|
||||
return RPMERR_SCRIPT;
|
||||
}
|
||||
|
||||
fprintf(f, rpmIsVerbose() ? "set -x\n\n" : "exec > /dev/null\n\n");
|
||||
fprintf(f, "umask 022\n");
|
||||
fprintf(f, "cd %s\n", rpmGetVar(RPMVAR_BUILDDIR));
|
||||
if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD) {
|
||||
fprintf(f, "cd %s\n", spec->buildSubdir);
|
||||
}
|
||||
if (what == RPMBUILD_RMBUILD) {
|
||||
fprintf(f, "rm -rf %s\n", spec->buildSubdir);
|
||||
} else {
|
||||
fprintf(f, "%s", getStringBuf(sb));
|
||||
}
|
||||
fprintf(f, "\nexit 0\n");
|
||||
|
||||
fclose(f);
|
||||
chmod(scriptName, 0600);
|
||||
|
||||
if (test) {
|
||||
FREE(scriptName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
wait(&status);
|
||||
if (! WIFEXITED(status) || WEXITSTATUS(status)) {
|
||||
rpmError(RPMERR_SCRIPT, "Bad exit status from %s (%s)",
|
||||
scriptName, name);
|
||||
FREE(scriptName);
|
||||
return RPMERR_SCRIPT;
|
||||
}
|
||||
|
||||
unlink(scriptName);
|
||||
FREE(scriptName);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeVars(Spec spec, FILE *f)
|
||||
{
|
||||
char *arch, *os, *s;
|
||||
|
||||
rpmGetArchInfo(&arch, NULL);
|
||||
rpmGetOsInfo(&os, NULL);
|
||||
|
||||
if (! main_package) {
|
||||
rpmError(RPMERR_INTERNAL, "Empty main package");
|
||||
exit(RPMERR_INTERNAL);
|
||||
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");
|
||||
}
|
||||
|
||||
if (makeTempFile(NULL, &script->name, &fd))
|
||||
exit(1);
|
||||
script->file = fdopen(fd, "w");
|
||||
|
||||
/* Prepare the script */
|
||||
fprintf(script->file,
|
||||
"# Script generated by rpm\n\n");
|
||||
|
||||
fprintf(script->file, "RPM_SOURCE_DIR=\"%s\"\n", rpmGetVar(RPMVAR_SOURCEDIR));
|
||||
fprintf(script->file, "RPM_BUILD_DIR=\"%s\"\n", rpmGetVar(RPMVAR_BUILDDIR));
|
||||
fprintf(script->file, "RPM_DOC_DIR=\"%s\"\n", rpmGetVar(RPMVAR_DEFAULTDOCDIR));
|
||||
fprintf(script->file, "RPM_OPT_FLAGS=\"%s\"\n", rpmGetVar(RPMVAR_OPTFLAGS));
|
||||
fprintf(script->file, "RPM_ARCH=\"%s\"\n", arch);
|
||||
fprintf(script->file, "RPM_OS=\"%s\"\n", os);
|
||||
if (rpmGetVar(RPMVAR_ROOT)) {
|
||||
fprintf(script->file, "RPM_ROOT_DIR=\"%s\"\n", rpmGetVar(RPMVAR_ROOT));
|
||||
} else {
|
||||
fprintf(script->file, "RPM_ROOT_DIR=\"\"\n");
|
||||
}
|
||||
if (rpmGetVar(RPMVAR_BUILDROOT)) {
|
||||
fprintf(script->file, "RPM_BUILD_ROOT=\"%s\"\n",
|
||||
rpmGetVar(RPMVAR_BUILDROOT));
|
||||
} else {
|
||||
fprintf(script->file, "RPM_BUILD_ROOT=\"\"\n");
|
||||
}
|
||||
|
||||
fprintf(script->file, "RPM_PACKAGE_NAME=\"%s\"\n", spec->name);
|
||||
headerGetEntry(main_package->header, RPMTAG_VERSION, &foo, (void **)&s, &foo);
|
||||
fprintf(script->file, "RPM_PACKAGE_VERSION=\"%s\"\n", s);
|
||||
headerGetEntry(main_package->header, RPMTAG_RELEASE, &foo, (void **)&s, &foo);
|
||||
fprintf(script->file, "RPM_PACKAGE_RELEASE=\"%s\"\n", s);
|
||||
|
||||
if (rpmIsVerbose()) {
|
||||
fprintf(script->file, "set -x\n\n");
|
||||
} else {
|
||||
fprintf(script->file, "exec > /dev/null\n\n");
|
||||
}
|
||||
|
||||
/* Set the umask to a known value */
|
||||
fprintf(script->file, "umask 022\n");
|
||||
|
||||
fprintf(script->file, "\necho Executing: %s\n", name);
|
||||
fprintf(script->file, "cd %s\n\n", rpmGetVar(RPMVAR_BUILDDIR));
|
||||
if (builddir) {
|
||||
/* Need to cd to the actual build directory. */
|
||||
/* Note that this means we have to parse the */
|
||||
/* %prep section even if we aren't using it. */
|
||||
fprintf(script->file, "cd %s\n\n", build_subdir);
|
||||
}
|
||||
|
||||
/* We do a litte sanity check here just to make sure we do not wipe */
|
||||
/* the system by accident... */
|
||||
if (rpmGetVar(RPMVAR_BUILDROOT)) {
|
||||
fprintf(script->file, "if [ -z \"$RPM_BUILD_ROOT\" -o \"$RPM_BUILD_ROOT\" = \"/\" ]; then\n");
|
||||
fprintf(script->file, " echo\n");
|
||||
fprintf(script->file, " echo 'Warning: Spec contains BuildRoot: tag that is either empty or is set to \"/\"'\n");
|
||||
fprintf(script->file, " echo\n");
|
||||
fprintf(script->file, " exit 1\n");
|
||||
fprintf(script->file, "fi\n");
|
||||
}
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
void writeScript(struct Script *script, char *s)
|
||||
{
|
||||
fprintf(script->file, "%s", s);
|
||||
}
|
||||
|
||||
int execScript(struct Script *script)
|
||||
{
|
||||
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);
|
||||
}
|
||||
package = package->next;
|
||||
}
|
||||
headerGetEntry(spec->packages->header, RPMTAG_NAME,
|
||||
NULL, (void **)&s, NULL);
|
||||
fprintf(f, "export RPM_PACKAGE_NAME=\"%s\"\n", s);
|
||||
headerGetEntry(spec->packages->header, RPMTAG_VERSION,
|
||||
NULL, (void **)&s, NULL);
|
||||
fprintf(f, "export RPM_PACKAGE_VERSION=\"%s\"\n", s);
|
||||
headerGetEntry(spec->packages->header, RPMTAG_RELEASE,
|
||||
NULL, (void **)&s, NULL);
|
||||
fprintf(f, "export RPM_PACKAGE_RELEASE=\"%s\"\n", s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int doSetupMacro(Spec spec, StringBuf sb, char *line)
|
||||
static void doRmSource(Spec spec)
|
||||
{
|
||||
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 }
|
||||
};
|
||||
struct Source *p;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if ((rc = poptParseArgvString(line, &argc, &argv))) {
|
||||
rpmError(RPMERR_BADSPEC, "Error parsing %%setup: %s",
|
||||
poptStrerror(rc));
|
||||
return RPMERR_BADSPEC;
|
||||
unlink(spec->specFile);
|
||||
|
||||
p = spec->sources;
|
||||
while (p) {
|
||||
if (! (p->flags & RPMBUILD_ISNO)) {
|
||||
sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), p->source);
|
||||
unlink(buf);
|
||||
}
|
||||
|
||||
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);
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
chptr = do_untar(spec, num, quietly);
|
||||
if (!chptr) return 1;
|
||||
|
||||
if (arg == 'a')
|
||||
appendLineStringBuf(after, chptr);
|
||||
else
|
||||
appendLineStringBuf(before, chptr);
|
||||
}
|
||||
|
||||
if (arg < -1) {
|
||||
rpmError(RPMERR_BADSPEC, "Bad %%setup option %s: %s",
|
||||
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
|
||||
poptStrerror(arg));
|
||||
free(argv);
|
||||
freeStringBuf(before);
|
||||
freeStringBuf(after);
|
||||
poptFreeContext(optCon);
|
||||
return(RPMERR_BADSPEC);
|
||||
}
|
||||
|
||||
if (dirName) {
|
||||
strcpy(build_subdir, dirName);
|
||||
} else {
|
||||
strcpy(build_subdir, spec->name);
|
||||
strcat(build_subdir, "-");
|
||||
/* We should already have a version field */
|
||||
headerGetEntry(spec->packages->header, RPMTAG_VERSION, NULL,
|
||||
(void *) &version, NULL);
|
||||
strcat(build_subdir, version);
|
||||
}
|
||||
|
||||
free(argv);
|
||||
poptFreeContext(optCon);
|
||||
|
||||
/* cd to the build dir */
|
||||
sprintf(buf, "cd %s", rpmGetVar(RPMVAR_BUILDDIR));
|
||||
appendLineStringBuf(sb, buf);
|
||||
|
||||
/* delete any old sources */
|
||||
if (!leaveDirs) {
|
||||
sprintf(buf, "rm -rf %s", build_subdir);
|
||||
appendLineStringBuf(sb, buf);
|
||||
}
|
||||
|
||||
/* if necessary, create and cd into the proper dir */
|
||||
if (createDir) {
|
||||
sprintf(buf, "mkdir -p %s\ncd %s", build_subdir, build_subdir);
|
||||
appendLineStringBuf(sb, buf);
|
||||
}
|
||||
|
||||
/* do the default action */
|
||||
if (!createDir && !skipDefaultAction) {
|
||||
chptr = do_untar(spec, 0, quietly);
|
||||
if (!chptr) return 1;
|
||||
appendLineStringBuf(sb, chptr);
|
||||
}
|
||||
|
||||
appendStringBuf(sb, getStringBuf(before));
|
||||
freeStringBuf(before);
|
||||
|
||||
if (!createDir) {
|
||||
sprintf(buf, "cd %s", build_subdir);
|
||||
appendLineStringBuf(sb, buf);
|
||||
}
|
||||
|
||||
if (createDir && !skipDefaultAction) {
|
||||
chptr = do_untar(spec, 0, quietly);
|
||||
if (!chptr) return 1;
|
||||
appendLineStringBuf(sb, chptr);
|
||||
}
|
||||
|
||||
appendStringBuf(sb, getStringBuf(after));
|
||||
freeStringBuf(after);
|
||||
|
||||
/* clean up permissions etc */
|
||||
if (!geteuid()) {
|
||||
appendLineStringBuf(sb, "chown -R root .");
|
||||
appendLineStringBuf(sb, "chgrp -R root .");
|
||||
}
|
||||
|
||||
if (rpmGetVar(RPMVAR_FIXPERMS)) {
|
||||
appendStringBuf(sb, "chmod -R ");
|
||||
appendStringBuf(sb, rpmGetVar(RPMVAR_FIXPERMS));
|
||||
appendLineStringBuf(sb, " .");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isCompressed(char *file)
|
||||
{
|
||||
int fd;
|
||||
unsigned char magic[4];
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
read(fd, magic, 4);
|
||||
close(fd);
|
||||
|
||||
if (((magic[0] == 0037) && (magic[1] == 0213)) || /* gzip */
|
||||
((magic[0] == 0037) && (magic[1] == 0236)) || /* old gzip */
|
||||
((magic[0] == 0037) && (magic[1] == 0036)) || /* pack */
|
||||
((magic[0] == 0037) && (magic[1] == 0240)) || /* SCO lzh */
|
||||
((magic[0] == 0037) && (magic[1] == 0235)) || /* compress */
|
||||
((magic[0] == 0120) && (magic[1] == 0113) &&
|
||||
(magic[2] == 0003) && (magic[3] == 0004)) /* pkzip */
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *do_untar(Spec spec, int c, int quietly)
|
||||
{
|
||||
static char buf[1024];
|
||||
char file[1024];
|
||||
char *s, *taropts;
|
||||
struct sources *sp;
|
||||
|
||||
s = NULL;
|
||||
sp = spec->sources;
|
||||
while (sp) {
|
||||
if ((sp->ispatch == 0) && (sp->num == c)) {
|
||||
s = sp->source;
|
||||
break;
|
||||
}
|
||||
sp = sp->next;
|
||||
}
|
||||
if (! s) {
|
||||
rpmError(RPMERR_BADSPEC, "No source number %d", c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(file, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), s);
|
||||
taropts = (rpmIsVerbose() && !quietly ? "-xvvf" : "-xf");
|
||||
|
||||
if (isCompressed(file)) {
|
||||
sprintf(buf,
|
||||
"%s -dc %s | tar %s -\n"
|
||||
"if [ $? -ne 0 ]; then\n"
|
||||
" exit $?\n"
|
||||
"fi",
|
||||
rpmGetVar(RPMVAR_GZIPBIN), file, taropts);
|
||||
} else {
|
||||
sprintf(buf, "tar %s %s", taropts, file);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *do_patch(Spec spec, int c, int strip, char *db,
|
||||
int reverse, int removeEmpties)
|
||||
{
|
||||
static char buf[1024];
|
||||
char file[1024];
|
||||
char args[1024];
|
||||
char *s;
|
||||
struct sources *sp;
|
||||
|
||||
s = NULL;
|
||||
sp = spec->sources;
|
||||
while (sp) {
|
||||
if ((sp->ispatch == 1) && (sp->num == c)) {
|
||||
s = sp->source;
|
||||
break;
|
||||
}
|
||||
sp = sp->next;
|
||||
}
|
||||
if (! s) {
|
||||
rpmError(RPMERR_BADSPEC, "No patch number %d", c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sprintf(file, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), s);
|
||||
|
||||
args[0] = '\0';
|
||||
if (db) {
|
||||
#if HAVE_OLDPATCH_21 == 0
|
||||
strcat(args, "-b ");
|
||||
#endif
|
||||
strcat(args, "--suffix ");
|
||||
strcat(args, db);
|
||||
}
|
||||
if (reverse) {
|
||||
strcat(args, " -R");
|
||||
}
|
||||
if (removeEmpties) {
|
||||
strcat(args, " -E");
|
||||
}
|
||||
|
||||
if (isCompressed(file)) {
|
||||
sprintf(buf,
|
||||
"echo \"Patch #%d:\"\n"
|
||||
"%s -dc %s | patch -p%d %s -s\n"
|
||||
"if [ $? -ne 0 ]; then\n"
|
||||
" exit $?\n"
|
||||
"fi",
|
||||
c, rpmGetVar(RPMVAR_GZIPBIN), file, strip, args);
|
||||
} else {
|
||||
sprintf(buf,
|
||||
"echo \"Patch #%d:\"\n"
|
||||
"patch -p%d %s -s < %s", c, strip, args, file);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int doPatchMacro(Spec spec, StringBuf sb, char *line)
|
||||
{
|
||||
char *opt_b;
|
||||
int opt_P, opt_p, opt_R, opt_E;
|
||||
char *s, *s1;
|
||||
char buf[1024];
|
||||
int patch_nums[1024]; /* XXX - we can only handle 1024 patches! */
|
||||
int patch_index, x;
|
||||
|
||||
opt_P = opt_p = opt_R = opt_E = 0;
|
||||
opt_b = NULL;
|
||||
patch_index = 0;
|
||||
|
||||
if (! strchr(" \t\n", line[6])) {
|
||||
/* %patchN */
|
||||
sprintf(buf, "%%patch -P %s", line + 6);
|
||||
} else {
|
||||
strcpy(buf, line);
|
||||
}
|
||||
|
||||
strtok(buf, " \t\n"); /* remove %patch */
|
||||
while ((s = strtok(NULL, " \t\n"))) {
|
||||
if (!strcmp(s, "-P")) {
|
||||
opt_P = 1;
|
||||
} else if (!strcmp(s, "-R")) {
|
||||
opt_R = 1;
|
||||
} else if (!strcmp(s, "-E")) {
|
||||
opt_E = 1;
|
||||
} else if (!strcmp(s, "-b")) {
|
||||
/* orig suffix */
|
||||
opt_b = strtok(NULL, " \t\n");
|
||||
if (! opt_b) {
|
||||
rpmError(RPMERR_BADSPEC, "Need arg to %%patch -b");
|
||||
return(RPMERR_BADSPEC);
|
||||
}
|
||||
} else if (!strncmp(s, "-p", 2)) {
|
||||
/* unfortunately, we must support -pX */
|
||||
if (! strchr(" \t\n", s[2])) {
|
||||
s = s + 2;
|
||||
} else {
|
||||
s = strtok(NULL, " \t\n");
|
||||
if (! s) {
|
||||
rpmError(RPMERR_BADSPEC, "Need arg to %%patch -p");
|
||||
return(RPMERR_BADSPEC);
|
||||
}
|
||||
}
|
||||
s1 = NULL;
|
||||
opt_p = strtoul(s, &s1, 10);
|
||||
if ((*s1) || (s1 == s) || (opt_p == ULONG_MAX)) {
|
||||
rpmError(RPMERR_BADSPEC, "Bad arg to %%patch -p: %s", s);
|
||||
return(RPMERR_BADSPEC);
|
||||
}
|
||||
} else {
|
||||
/* Must be a patch num */
|
||||
if (patch_index == 1024) {
|
||||
rpmError(RPMERR_BADSPEC, "Too many patches!");
|
||||
return(RPMERR_BADSPEC);
|
||||
}
|
||||
s1 = NULL;
|
||||
patch_nums[patch_index] = strtoul(s, &s1, 10);
|
||||
if ((*s1) || (s1 == s) || (patch_nums[patch_index] == ULONG_MAX)) {
|
||||
rpmError(RPMERR_BADSPEC, "Bad arg to %%patch: %s", s);
|
||||
return(RPMERR_BADSPEC);
|
||||
}
|
||||
patch_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/* All args processed */
|
||||
|
||||
if (! opt_P) {
|
||||
s = do_patch(spec, 0, opt_p, opt_b, opt_R, opt_E);
|
||||
if (! s) {
|
||||
return 1;
|
||||
}
|
||||
appendLineStringBuf(sb, s);
|
||||
}
|
||||
|
||||
x = 0;
|
||||
while (x < patch_index) {
|
||||
s = do_patch(spec, patch_nums[x], opt_p, opt_b, opt_R, opt_E);
|
||||
if (! s) {
|
||||
return 1;
|
||||
}
|
||||
appendLineStringBuf(sb, s);
|
||||
x++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int checkSources(Spec s)
|
||||
{
|
||||
struct sources *source;
|
||||
struct PackageRec *package;
|
||||
char buf[1024];
|
||||
|
||||
/* Check that we can access all the sources */
|
||||
source = s->sources;
|
||||
while (source) {
|
||||
sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), source->source);
|
||||
if (access(buf, R_OK)) {
|
||||
rpmError(RPMERR_BADSPEC, "missing source or patch: %s", buf);
|
||||
return RPMERR_BADSPEC;
|
||||
}
|
||||
source = source->next;
|
||||
}
|
||||
|
||||
/* ... and icons */
|
||||
package = s->packages;
|
||||
while (package) {
|
||||
if (package->icon) {
|
||||
sprintf(buf, "%s/%s", rpmGetVar(RPMVAR_SOURCEDIR), package->icon);
|
||||
if (access(buf, R_OK)) {
|
||||
rpmError(RPMERR_BADSPEC, "missing icon: %s", buf);
|
||||
return RPMERR_BADSPEC;
|
||||
}
|
||||
}
|
||||
package = package->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int execPrep(Spec s, int really_exec, int test)
|
||||
{
|
||||
char **lines, **lines1, *p;
|
||||
StringBuf out;
|
||||
int res;
|
||||
|
||||
if (checkSources(s)) {
|
||||
return 1;
|
||||
}
|
||||
out = newStringBuf();
|
||||
|
||||
p = getStringBuf(s->prep);
|
||||
lines = splitString(p, strlen(p), '\n');
|
||||
lines1 = lines;
|
||||
while (*lines) {
|
||||
if (! strncmp(*lines, "%setup", 6)) {
|
||||
if (doSetupMacro(s, out, *lines)) {
|
||||
return 1;
|
||||
}
|
||||
} else if (! strncmp(*lines, "%patch", 6)) {
|
||||
if (doPatchMacro(s, out, *lines)) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
appendLineStringBuf(out, *lines);
|
||||
}
|
||||
lines++;
|
||||
}
|
||||
|
||||
freeSplitString(lines1);
|
||||
res = 0;
|
||||
if (really_exec) {
|
||||
res = execPart(s, getStringBuf(out), "%prep", 0, test);
|
||||
}
|
||||
freeStringBuf(out);
|
||||
return res;
|
||||
}
|
||||
|
||||
int execBuild(Spec s, int test)
|
||||
{
|
||||
return execPart(s, getStringBuf(s->build), "%build", 1, test);
|
||||
}
|
||||
|
||||
int execInstall(Spec s, int test)
|
||||
{
|
||||
int res;
|
||||
|
||||
if ((res = execPart(s, getStringBuf(s->install), "%install", 1, test))) {
|
||||
return res;
|
||||
}
|
||||
if ((res = finish_filelists(s))) {
|
||||
return res;
|
||||
}
|
||||
return execPart(s, getStringBuf(s->doc), "special doc", 1, test);
|
||||
}
|
||||
|
||||
int execClean(Spec s)
|
||||
{
|
||||
return execPart(s, getStringBuf(s->clean), "%clean", 1, 0);
|
||||
}
|
||||
|
||||
int verifyList(Spec s)
|
||||
{
|
||||
int res;
|
||||
|
||||
if ((res = finish_filelists(s))) {
|
||||
return res;
|
||||
}
|
||||
return packageBinaries(s, NULL, PACK_NOPACKAGE);
|
||||
}
|
||||
|
||||
int doBuild(Spec s, int flags, char *passPhrase)
|
||||
{
|
||||
int test;
|
||||
|
||||
test = flags & RPMBUILD_TEST;
|
||||
|
||||
strcpy(build_subdir, ".");
|
||||
|
||||
if (s->buildArch) {
|
||||
rpmSetMachine(s->buildArch, NULL);
|
||||
}
|
||||
|
||||
/* We always need to parse the %prep section */
|
||||
if (execPrep(s, (flags & RPMBUILD_PREP), test)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (flags & RPMBUILD_LIST)
|
||||
return verifyList(s);
|
||||
|
||||
if (flags & RPMBUILD_BUILD) {
|
||||
if (execBuild(s, test)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & RPMBUILD_INSTALL) {
|
||||
if (execInstall(s, test)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (test) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
markBuildTime();
|
||||
|
||||
if (flags & RPMBUILD_BINARY) {
|
||||
if (packageBinaries(s, passPhrase, PACK_PACKAGE)) {
|
||||
return 1;
|
||||
}
|
||||
if (execClean(s)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & RPMBUILD_SOURCE) {
|
||||
if (packageSource(s, passPhrase)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & RPMBUILD_SWEEP) {
|
||||
doSweep(s);
|
||||
}
|
||||
|
||||
if (flags & RPMBUILD_RMSOURCE) {
|
||||
doRmSource(s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
#define RPMBUILD_PREP (1 << 0)
|
||||
#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_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_TEST (1 << 8)
|
||||
#define RPMBUILD_RMBUILD (1 << 8)
|
||||
#define RPMBUILD_STRINGBUF (1 << 9) /* only for doScript() */
|
||||
|
||||
#endif _BUILD_H_
|
||||
int buildSpec(Spec spec, int what, int test);
|
||||
|
||||
int doScript(Spec spec, int what, char *name, StringBuf sb, int test);
|
||||
|
|
1982
build/files.c
1982
build/files.c
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,8 @@
|
|||
#ifndef _FILES_H_
|
||||
#define _FILES_H_
|
||||
|
||||
#include "spec.h"
|
||||
#include "specP.h"
|
||||
#include "stringbuf.h"
|
||||
#include "package.h"
|
||||
#include "lib/cpio.h"
|
||||
|
||||
int finish_filelists(Spec spec);
|
||||
|
||||
int process_filelist(Header header, struct PackageRec *pr, StringBuf sb,
|
||||
int *size, char *name, char *version,
|
||||
char *release, int type, char *prefix, char *specFile);
|
||||
|
||||
#endif _FILES_H_
|
||||
int processBinaryFiles(Spec spec, int installSpecialDoc);
|
||||
int processSourceFiles(Spec spec);
|
||||
void freeCpioList(struct cpioFileMapping *cpioList, int cpioCount);
|
||||
|
|
212
build/macro.c
212
build/macro.c
|
@ -4,48 +4,42 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "macro.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "macro.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef DEBUG_MACROS
|
||||
#include <stdio.h>
|
||||
#define rpmError fprintf
|
||||
#define RPMERR_BADSPEC stderr
|
||||
static void dumpTable(void);
|
||||
#else
|
||||
#include "rpmlib.h"
|
||||
#include "lib/rpmlib.h"
|
||||
#endif
|
||||
|
||||
static void expandMacroTable(void);
|
||||
static void expandMacroTable(struct MacroContext *mc);
|
||||
static int compareMacros(const void *ap, const void *bp);
|
||||
static struct macroEntry *findEntry(char *name);
|
||||
static int handleDefine(char *buf);
|
||||
static struct MacroEntry *findEntry(struct MacroContext *mc, char *name);
|
||||
static int handleDefine(struct MacroContext *mc, char *buf);
|
||||
static int parseMacro(char *p, char **macro, char **next);
|
||||
|
||||
/* This should be a hash table, but I doubt anyone will ever notice */
|
||||
/* This should be a hash table, but I doubt anyone would ever */
|
||||
/* notice the increase is speed. */
|
||||
|
||||
#define MACRO_CHUNK_SIZE 16
|
||||
|
||||
struct macroEntry {
|
||||
char *name;
|
||||
char *expansion;
|
||||
};
|
||||
|
||||
static struct macroEntry *macroTable = NULL;
|
||||
static int macrosAllocated = 0;
|
||||
static int firstFree = 0;
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Parsing routines */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
int expandMacros(char *buf)
|
||||
int expandMacros(struct MacroContext *mc, char *buf)
|
||||
{
|
||||
char bufA[1024];
|
||||
char *copyTo, *copyFrom;
|
||||
char *name, *rest, *first;
|
||||
struct macroEntry *p;
|
||||
struct MacroEntry *p;
|
||||
|
||||
if (! buf) {
|
||||
return 0;
|
||||
|
@ -57,6 +51,7 @@ int expandMacros(char *buf)
|
|||
first++;
|
||||
}
|
||||
if (*first == '#') {
|
||||
buf[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -70,8 +65,8 @@ int expandMacros(char *buf)
|
|||
if (parseMacro(copyFrom+1, &name, &rest)) {
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(name, "define")) {
|
||||
if (handleDefine(rest)) {
|
||||
if (copyFrom == buf && !strcmp(name, "define")) {
|
||||
if (handleDefine(mc, rest)) {
|
||||
return 1;
|
||||
}
|
||||
/* result is empty */
|
||||
|
@ -83,7 +78,7 @@ int expandMacros(char *buf)
|
|||
copyFrom = rest;
|
||||
} else {
|
||||
/* a real live macro! */
|
||||
p = findEntry(name);
|
||||
p = findEntry(mc, name);
|
||||
if (! p) {
|
||||
/* undefined - just leave it */
|
||||
*copyTo++ = '%';
|
||||
|
@ -116,7 +111,7 @@ static int parseMacro(char *p, char **macro, char **next)
|
|||
|
||||
if (! p) {
|
||||
/* empty macro name */
|
||||
rpmError(RPMERR_BADSPEC, "Empty macro name\n");
|
||||
rpmError(RPMERR_BADSPEC, "Empty macro name");
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -124,14 +119,14 @@ static int parseMacro(char *p, char **macro, char **next)
|
|||
*next = strchr(p, '}');
|
||||
if (! *next) {
|
||||
/* unterminated */
|
||||
rpmError(RPMERR_BADSPEC, "Unterminated {: %s\n", p);
|
||||
rpmError(RPMERR_BADSPEC, "Unterminated {: %s", p);
|
||||
return 1;
|
||||
}
|
||||
**next = '\0';
|
||||
*macro = strtok(p+1, " \n\t");
|
||||
if (! *macro) {
|
||||
/* empty macro name */
|
||||
rpmError(RPMERR_BADSPEC, "Empty macro name\n");
|
||||
rpmError(RPMERR_BADSPEC, "Empty macro name");
|
||||
return 2;
|
||||
}
|
||||
(*next)++;
|
||||
|
@ -146,7 +141,7 @@ static int parseMacro(char *p, char **macro, char **next)
|
|||
|
||||
if (isspace(*p) || ! *p) {
|
||||
/* illegal % syntax */
|
||||
rpmError(RPMERR_BADSPEC, "Illegal %% syntax: %s\n", p);
|
||||
rpmError(RPMERR_BADSPEC, "Illegal %% syntax: %s", p);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
@ -165,7 +160,7 @@ static int parseMacro(char *p, char **macro, char **next)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int handleDefine(char *buf)
|
||||
static int handleDefine(struct MacroContext *mc, char *buf)
|
||||
{
|
||||
char *last, *name, *expansion;
|
||||
|
||||
|
@ -177,7 +172,7 @@ static int handleDefine(char *buf)
|
|||
}
|
||||
if (! *name) {
|
||||
/* missing macro name */
|
||||
rpmError(RPMERR_BADSPEC, "Unfinished %%define\n");
|
||||
rpmError(RPMERR_BADSPEC, "Unfinished %%define");
|
||||
return 1;
|
||||
}
|
||||
expansion = name;
|
||||
|
@ -201,13 +196,96 @@ static int handleDefine(char *buf)
|
|||
}
|
||||
}
|
||||
|
||||
expandMacros(expansion);
|
||||
addMacro(name, expansion);
|
||||
expandMacros(mc, expansion);
|
||||
addMacro(mc, name, expansion);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Table handling routines */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
void initMacros(struct MacroContext *mc)
|
||||
{
|
||||
mc->macrosAllocated = 0;
|
||||
mc->firstFree = 0;
|
||||
mc->macroTable = NULL;
|
||||
expandMacroTable(mc);
|
||||
|
||||
}
|
||||
|
||||
void freeMacros(struct MacroContext *mc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mc->firstFree; i++) {
|
||||
FREE(mc->macroTable[i].name);
|
||||
FREE(mc->macroTable[i].expansion);
|
||||
}
|
||||
FREE(mc->macroTable);
|
||||
}
|
||||
|
||||
void addMacro(struct MacroContext *mc, char *name, char *expansion)
|
||||
{
|
||||
struct MacroEntry *p;
|
||||
|
||||
p = findEntry(mc, name);
|
||||
if (p) {
|
||||
free(p->expansion);
|
||||
p->expansion = strdup(expansion);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mc->firstFree == mc->macrosAllocated) {
|
||||
expandMacroTable(mc);
|
||||
}
|
||||
|
||||
p = mc->macroTable + mc->firstFree++;
|
||||
p->name = strdup(name);
|
||||
p->expansion = strdup(expansion);
|
||||
|
||||
qsort(mc->macroTable, mc->firstFree, sizeof(*(mc->macroTable)),
|
||||
compareMacros);
|
||||
}
|
||||
|
||||
static struct MacroEntry *findEntry(struct MacroContext *mc, char *name)
|
||||
{
|
||||
struct MacroEntry key;
|
||||
|
||||
if (! mc->firstFree) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key.name = name;
|
||||
return bsearch(&key, mc->macroTable, mc->firstFree,
|
||||
sizeof(*(mc->macroTable)), compareMacros);
|
||||
}
|
||||
|
||||
static int compareMacros(const void *ap, const void *bp)
|
||||
{
|
||||
return strcmp(((struct MacroEntry *)ap)->name,
|
||||
((struct MacroEntry *)bp)->name);
|
||||
}
|
||||
|
||||
static void expandMacroTable(struct MacroContext *mc)
|
||||
{
|
||||
mc->macrosAllocated += MACRO_CHUNK_SIZE;
|
||||
if (! mc->macrosAllocated) {
|
||||
mc->macroTable = malloc(sizeof(*(mc->macroTable)) *
|
||||
mc->macrosAllocated);
|
||||
mc->firstFree = 0;
|
||||
} else {
|
||||
mc->macroTable = realloc(mc->macroTable, sizeof(*(mc->macroTable)) *
|
||||
mc->macrosAllocated);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
#ifdef DEBUG_MACROS
|
||||
static void dumpTable()
|
||||
{
|
||||
int i;
|
||||
|
@ -230,77 +308,3 @@ void main(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* Table handling routines */
|
||||
/* */
|
||||
/*************************************************************************/
|
||||
|
||||
void resetMacros(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (! macrosAllocated) {
|
||||
expandMacroTable();
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < firstFree; i++) {
|
||||
free(macroTable[i].name);
|
||||
free(macroTable[i].expansion);
|
||||
}
|
||||
firstFree = 0;
|
||||
}
|
||||
|
||||
void addMacro(char *name, char *expansion)
|
||||
{
|
||||
struct macroEntry *p;
|
||||
|
||||
p = findEntry(name);
|
||||
if (p) {
|
||||
free(p->expansion);
|
||||
p->expansion = strdup(expansion);
|
||||
return;
|
||||
}
|
||||
|
||||
if (firstFree == macrosAllocated) {
|
||||
expandMacroTable();
|
||||
}
|
||||
|
||||
p = macroTable + firstFree++;
|
||||
p->name = strdup(name);
|
||||
p->expansion = strdup(expansion);
|
||||
|
||||
qsort(macroTable, firstFree, sizeof(*macroTable), compareMacros);
|
||||
}
|
||||
|
||||
static struct macroEntry *findEntry(char *name)
|
||||
{
|
||||
struct macroEntry key;
|
||||
|
||||
if (! firstFree) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key.name = name;
|
||||
return bsearch(&key, macroTable, firstFree,
|
||||
sizeof(*macroTable), compareMacros);
|
||||
}
|
||||
|
||||
static int compareMacros(const void *ap, const void *bp)
|
||||
{
|
||||
return strcmp(((struct macroEntry *)ap)->name,
|
||||
((struct macroEntry *)bp)->name);
|
||||
}
|
||||
|
||||
static void expandMacroTable()
|
||||
{
|
||||
macrosAllocated += MACRO_CHUNK_SIZE;
|
||||
if (! macrosAllocated) {
|
||||
macroTable = malloc(sizeof(*macroTable) * macrosAllocated);
|
||||
firstFree = 0;
|
||||
} else {
|
||||
macroTable = realloc(macroTable,
|
||||
sizeof(*macroTable) * macrosAllocated);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,25 @@
|
|||
#ifndef _MACRO_H_
|
||||
#define _MACRO_H_
|
||||
|
||||
/* macro.h - %macro handling */
|
||||
|
||||
void resetMacros(void);
|
||||
struct MacroEntry {
|
||||
char *name;
|
||||
char *expansion;
|
||||
};
|
||||
|
||||
void addMacro(char *name, char *expansion);
|
||||
struct MacroContext {
|
||||
struct MacroEntry *macroTable;
|
||||
int macrosAllocated;
|
||||
int firstFree;
|
||||
};
|
||||
|
||||
void initMacros(struct MacroContext *mc);
|
||||
void freeMacros(struct MacroContext *mc);
|
||||
|
||||
void addMacro(struct MacroContext *mc, char *name, char *expansion);
|
||||
|
||||
/* Expand all macros in buf, in place */
|
||||
int expandMacros(char *buf);
|
||||
int expandMacros(struct MacroContext *mc, char *buf);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_
|
||||
|
|
942
build/pack.c
942
build/pack.c
File diff suppressed because it is too large
Load Diff
14
build/pack.h
14
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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, ¯o, 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -1,22 +1,50 @@
|
|||
/* handle triggers */
|
||||
|
||||
#include "config.h"
|
||||
#include "miscfn.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "trigger.h"
|
||||
#include "header.h"
|
||||
#include "spec.h"
|
||||
#include "specP.h"
|
||||
#include "messages.h"
|
||||
#include "rpmlib.h"
|
||||
#include "stringbuf.h"
|
||||
#include "misc.h"
|
||||
/* %trigger is a strange combination of %pre and Requires: behavior */
|
||||
/* We can handle it by handing the args before "--" to parseScript, */
|
||||
/* which in the case of triggers should return an index. We then */
|
||||
/* can pass the remaining arguments to parseReqProv, along with the */
|
||||
/* index we just obtained. In theory, then, all script arguments */
|
||||
/* and behavior is in parseScript, and the require behavior is in */
|
||||
/* parseReqProv, with just a little glue used here. */
|
||||
|
||||
#define FREE(x) { if (x) free(x); }
|
||||
#define CHUNK 8
|
||||
int parseTrigger(Spec spec, int parsePart)
|
||||
{
|
||||
int nextPart;
|
||||
char **lineArgv, **triggerArgv;
|
||||
int lineArgc, triggerArgc;
|
||||
int rc, dash;
|
||||
|
||||
if ((rc = poptParseArgvString(spec->line, &lineArgc, &lineArgv))) {
|
||||
rpmError(RPMERR_BADSPEC, "line %d: Error parsing trigger options: %s",
|
||||
spec->lineNum, partname, poptStrerror(rc));
|
||||
return RPMERR_BADSPEC;
|
||||
}
|
||||
triggerArgv = lineArgv;
|
||||
triggerArgc = lineArgc;
|
||||
|
||||
dash = 0;
|
||||
while (dash <= lineArgc) {
|
||||
if (!strcmp(lineArgv[dash], "--")) {
|
||||
lineArgv[dash] = NULL;
|
||||
if ((rc = parseScriptArgs(spec, dash, lineArgv,
|
||||
&prog, &name, &flag))) {
|
||||
free(lineArgv);
|
||||
return rc;
|
||||
}
|
||||
triggerArgv = &(lineArgv[dash + 1]);
|
||||
triggerArgc = lineArgc - dash - 1;
|
||||
break;
|
||||
}
|
||||
dash++;
|
||||
}
|
||||
|
||||
if ((rc = parseReqArgs(spec, triggerArgc, triggerArgv,
|
||||
|
||||
}
|
||||
|
||||
int addTrigger(struct PackageRec *package,
|
||||
int sense, char *script, char *args)
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
476
build/reqprov.c
476
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;
|
||||
char **names;
|
||||
char **versions = NULL;
|
||||
int *flags = NULL;
|
||||
int nametag = 0;
|
||||
int versiontag = 0;
|
||||
int flagtag = 0;
|
||||
int len;
|
||||
int extra = 0;
|
||||
|
||||
/* 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;
|
||||
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 {
|
||||
same = 0;
|
||||
nametag = RPMTAG_REQUIRENAME;
|
||||
versiontag = RPMTAG_REQUIREVERSION;
|
||||
flagtag = RPMTAG_REQUIREFLAGS;
|
||||
}
|
||||
|
||||
if (same && !strcmp(rd->name, name)) {
|
||||
/* They are exacty the same */
|
||||
break;
|
||||
flag = (flag & RPMSENSE_SENSEMASK) | extra;
|
||||
if (!version) {
|
||||
version = "";
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
rd = rd->next;
|
||||
}
|
||||
if (rd) {
|
||||
/* already there */
|
||||
rpmMessage(RPMMESS_DEBUG, "Already Got: %s\n", name);
|
||||
while (len) {
|
||||
len--;
|
||||
if (!strcmp(names[len], name)) {
|
||||
if (!flagtag ||
|
||||
(!strcmp(versions[len], version) && flags[len] == flag)) {
|
||||
/* The same */
|
||||
FREE(names);
|
||||
FREE(versions);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
FREE(names);
|
||||
FREE(versions);
|
||||
}
|
||||
|
||||
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++;
|
||||
} else {
|
||||
rpmMessage(RPMMESS_DEBUG, "Adding require: %s\n", name);
|
||||
p->numReq++;
|
||||
headerAddOrAppendEntry(pkg->header, nametag,
|
||||
RPM_STRING_ARRAY_TYPE, &name, 1);
|
||||
if (flagtag) {
|
||||
headerAddOrAppendEntry(pkg->header, versiontag,
|
||||
RPM_STRING_ARRAY_TYPE, &version, 1);
|
||||
headerAddOrAppendEntry(pkg->header, flagtag,
|
||||
RPM_INT32_TYPE, &flag, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
/* */
|
||||
/* Add require/provides for the files in the header */
|
||||
/* (adds to the package structure) */
|
||||
/* */
|
||||
/*************************************************************/
|
||||
|
||||
static StringBuf getOutputFrom(char *dir, char *argv[],
|
||||
char *writePtr, int writeBytesLeft,
|
||||
int failNonZero)
|
||||
int generateAutoReqProv(Spec spec, Package pkg,
|
||||
struct cpioFileMapping *cpioList, int cpioCount)
|
||||
{
|
||||
int progPID;
|
||||
int progDead;
|
||||
int toProg[2];
|
||||
int fromProg[2];
|
||||
int status;
|
||||
void *oldhandler;
|
||||
int bytesWritten;
|
||||
StringBuf readBuff;
|
||||
int bytes;
|
||||
unsigned char buf[8193];
|
||||
|
||||
oldhandler = signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
pipe(toProg);
|
||||
pipe(fromProg);
|
||||
|
||||
if (!(progPID = fork())) {
|
||||
close(toProg[1]);
|
||||
close(fromProg[0]);
|
||||
|
||||
dup2(toProg[0], 0); /* Make stdin the in pipe */
|
||||
dup2(fromProg[1], 1); /* Make stdout the out pipe */
|
||||
|
||||
close(toProg[0]);
|
||||
close(fromProg[1]);
|
||||
|
||||
chdir(dir);
|
||||
|
||||
execvp(argv[0], argv);
|
||||
rpmError(RPMERR_EXEC, "Couldn't exec %s", argv[0]);
|
||||
_exit(RPMERR_EXEC);
|
||||
}
|
||||
if (progPID < 0) {
|
||||
rpmError(RPMERR_FORK, "Couldn't fork %s", argv[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
close(toProg[0]);
|
||||
close(fromProg[1]);
|
||||
|
||||
/* Do not block reading or writing from/to prog. */
|
||||
fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
|
||||
fcntl(toProg[1], F_SETFL, O_NONBLOCK);
|
||||
|
||||
readBuff = newStringBuf();
|
||||
|
||||
progDead = 0;
|
||||
do {
|
||||
if (waitpid(progPID, &status, WNOHANG)) {
|
||||
progDead = 1;
|
||||
}
|
||||
|
||||
/* Write some stuff to the process if possible */
|
||||
if (writeBytesLeft) {
|
||||
if ((bytesWritten =
|
||||
write(toProg[1], writePtr,
|
||||
(1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
perror("getOutputFrom()");
|
||||
exit(1);
|
||||
}
|
||||
bytesWritten = 0;
|
||||
}
|
||||
writeBytesLeft -= bytesWritten;
|
||||
writePtr += bytesWritten;
|
||||
} else {
|
||||
close(toProg[1]);
|
||||
}
|
||||
|
||||
/* Read any data from prog */
|
||||
bytes = read(fromProg[0], buf, sizeof(buf)-1);
|
||||
while (bytes > 0) {
|
||||
buf[bytes] = '\0';
|
||||
appendStringBuf(readBuff, buf);
|
||||
bytes = read(fromProg[0], buf, sizeof(buf)-1);
|
||||
}
|
||||
|
||||
/* terminate when prog dies */
|
||||
} while (!progDead);
|
||||
|
||||
close(toProg[1]);
|
||||
close(fromProg[0]);
|
||||
signal(SIGPIPE, oldhandler);
|
||||
|
||||
if (writeBytesLeft) {
|
||||
rpmError(RPMERR_EXEC, "failed to write all data to %s", argv[0]);
|
||||
return NULL;
|
||||
}
|
||||
waitpid(progPID, &status, 0);
|
||||
if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
|
||||
rpmError(RPMERR_EXEC, "%s failed", argv[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return readBuff;
|
||||
}
|
||||
|
||||
int generateAutoReqProv(Header header, struct PackageRec *p)
|
||||
{
|
||||
char **f, **fsave, *s;
|
||||
int count;
|
||||
int_16 *modes;
|
||||
|
||||
StringBuf writeBuff;
|
||||
StringBuf readBuff;
|
||||
char *writePtr;
|
||||
StringBuf writeBuf;
|
||||
int writeBytes;
|
||||
char dir[1024];
|
||||
char *argv[8];
|
||||
StringBuf readBuf;
|
||||
char *argv[2];
|
||||
char **f, **fsave;
|
||||
|
||||
rpmMessage(RPMMESS_VERBOSE, "Finding dependencies...\n");
|
||||
|
||||
/*** Get root directory ***/
|
||||
|
||||
if (rpmGetVar(RPMVAR_ROOT)) {
|
||||
strcpy(dir, rpmGetVar(RPMVAR_ROOT));
|
||||
} else {
|
||||
strcpy(dir, "/");
|
||||
}
|
||||
|
||||
/*** Generate File List ***/
|
||||
|
||||
if (!headerGetEntry(header, RPMTAG_FILENAMES, NULL, (void **) &f, &count)) {
|
||||
if (!cpioCount) {
|
||||
return 0;
|
||||
}
|
||||
if (!count) {
|
||||
return 0;
|
||||
}
|
||||
fsave = f;
|
||||
headerGetEntry(header, RPMTAG_FILEMODES, NULL, (void **) &modes, NULL);
|
||||
|
||||
writeBuff = newStringBuf();
|
||||
writeBuf = newStringBuf();
|
||||
writeBytes = 0;
|
||||
while (count--) {
|
||||
s = *f++;
|
||||
/* We skip the leading "/" (already normalized) */
|
||||
writeBytes += strlen(s);
|
||||
appendLineStringBuf(writeBuff, s + 1);
|
||||
while (cpioCount--) {
|
||||
writeBytes += strlen(cpioList->fsPath) + 1;
|
||||
appendLineStringBuf(writeBuf, cpioList->fsPath);
|
||||
cpioList++;
|
||||
}
|
||||
if (fsave) {
|
||||
free(fsave);
|
||||
}
|
||||
writePtr = getStringBuf(writeBuff);
|
||||
|
||||
/*** Do Provides ***/
|
||||
|
||||
rpmMessage(RPMMESS_NORMAL, "Finding provides...\n");
|
||||
|
||||
argv[0] = "find-provides";
|
||||
argv[1] = NULL;
|
||||
readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 1);
|
||||
if (!readBuff) {
|
||||
readBuf = getOutputFrom(NULL, argv,
|
||||
getStringBuf(writeBuf), writeBytes, 1);
|
||||
if (!readBuf) {
|
||||
rpmError(RPMERR_EXEC, "Failed to find provides");
|
||||
exit(1);
|
||||
freeStringBuf(writeBuf);
|
||||
return RPMERR_EXEC;
|
||||
}
|
||||
|
||||
s = getStringBuf(readBuff);
|
||||
f = fsave = splitString(s, strlen(s), '\n');
|
||||
freeStringBuf(readBuff);
|
||||
f = fsave = splitString(getStringBuf(readBuf),
|
||||
strlen(getStringBuf(readBuf)), '\n');
|
||||
freeStringBuf(readBuf);
|
||||
while (*f) {
|
||||
if (**f) {
|
||||
addReqProv(p, RPMSENSE_PROVIDES, *f, NULL);
|
||||
addReqProv(spec, pkg, RPMSENSE_PROVIDES, *f, NULL);
|
||||
}
|
||||
f++;
|
||||
}
|
||||
free(fsave);
|
||||
FREE(fsave);
|
||||
|
||||
/*** Do Requires ***/
|
||||
|
||||
rpmMessage(RPMMESS_NORMAL, "Finding requires...\n");
|
||||
|
||||
argv[0] = "find-requires";
|
||||
argv[1] = NULL;
|
||||
readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 0);
|
||||
if (!readBuff) {
|
||||
readBuf = getOutputFrom(NULL, argv,
|
||||
getStringBuf(writeBuf), writeBytes, 0);
|
||||
if (!readBuf) {
|
||||
rpmError(RPMERR_EXEC, "Failed to find requires");
|
||||
exit(1);
|
||||
freeStringBuf(writeBuf);
|
||||
return RPMERR_EXEC;
|
||||
}
|
||||
|
||||
s = getStringBuf(readBuff);
|
||||
f = fsave = splitString(s, strlen(s), '\n');
|
||||
freeStringBuf(readBuff);
|
||||
f = fsave = splitString(getStringBuf(readBuf),
|
||||
strlen(getStringBuf(readBuf)), '\n');
|
||||
freeStringBuf(readBuf);
|
||||
while (*f) {
|
||||
if (**f) {
|
||||
addReqProv(p, RPMSENSE_ANY, *f, NULL);
|
||||
addReqProv(spec, pkg, RPMSENSE_ANY, *f, NULL);
|
||||
}
|
||||
f++;
|
||||
}
|
||||
free(fsave);
|
||||
FREE(fsave);
|
||||
|
||||
/*** Clean Up ***/
|
||||
|
||||
freeStringBuf(writeBuff);
|
||||
freeStringBuf(writeBuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
/* */
|
||||
/* Generate and add header entry from package record */
|
||||
/* */
|
||||
/*************************************************************/
|
||||
|
||||
int processReqProv(Header h, struct PackageRec *p)
|
||||
void printReqs(Spec spec, Package pkg)
|
||||
{
|
||||
struct ReqProv *rd;
|
||||
char **nameArray, **namePtr;
|
||||
char **versionArray, **versionPtr;
|
||||
int_32 *flagArray, *flagPtr;
|
||||
int x;
|
||||
int startedPreReq = 0;
|
||||
int startedReq = 0;
|
||||
|
||||
if (p->numProv) {
|
||||
rd = p->reqprov;
|
||||
nameArray = namePtr = malloc(p->numProv * sizeof(*nameArray));
|
||||
rpmMessage(RPMMESS_VERBOSE, "Provides (%d):", p->numProv);
|
||||
while (rd) {
|
||||
if (rd->flags & RPMSENSE_PROVIDES) {
|
||||
rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
|
||||
*namePtr++ = rd->name;
|
||||
}
|
||||
rd = rd->next;
|
||||
}
|
||||
rpmMessage(RPMMESS_VERBOSE, "\n");
|
||||
char **names;
|
||||
int x, count;
|
||||
int *flags;
|
||||
|
||||
headerAddEntry(h, RPMTAG_PROVIDES, RPM_STRING_ARRAY_TYPE, nameArray, p->numProv);
|
||||
free(nameArray);
|
||||
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_NORMAL, "\n");
|
||||
FREE(names);
|
||||
}
|
||||
|
||||
if (p->numObsoletes) {
|
||||
rd = p->reqprov;
|
||||
nameArray = namePtr = malloc(p->numObsoletes * sizeof(*nameArray));
|
||||
rpmMessage(RPMMESS_VERBOSE, "Obsoletes (%d):", p->numObsoletes);
|
||||
while (rd) {
|
||||
if (rd->flags & RPMSENSE_OBSOLETES) {
|
||||
rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
|
||||
*namePtr++ = rd->name;
|
||||
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;
|
||||
}
|
||||
rd = rd->next;
|
||||
rpmMessage(RPMMESS_NORMAL, " %s", names[x]);
|
||||
}
|
||||
rpmMessage(RPMMESS_VERBOSE, "\n");
|
||||
|
||||
headerAddEntry(h, RPMTAG_OBSOLETES, RPM_STRING_ARRAY_TYPE, nameArray, p->numObsoletes);
|
||||
free(nameArray);
|
||||
x++;
|
||||
}
|
||||
rpmMessage(RPMMESS_NORMAL, "\n");
|
||||
x = 0;
|
||||
while (x < count) {
|
||||
if (! (flags[x] & RPMSENSE_PREREQ)) {
|
||||
if (! startedReq) {
|
||||
rpmMessage(RPMMESS_NORMAL, "Requires:");
|
||||
startedReq = 1;
|
||||
}
|
||||
rpmMessage(RPMMESS_NORMAL, " %s", names[x]);
|
||||
}
|
||||
x++;
|
||||
}
|
||||
rpmMessage(RPMMESS_NORMAL, "\n");
|
||||
FREE(names);
|
||||
}
|
||||
|
||||
if (p->numConflict) {
|
||||
rd = p->reqprov;
|
||||
nameArray = namePtr = malloc(p->numConflict * sizeof(*nameArray));
|
||||
versionArray = versionPtr =
|
||||
malloc(p->numConflict * sizeof(*versionArray));
|
||||
flagArray = flagPtr = malloc(p->numConflict * sizeof(*flagArray));
|
||||
rpmMessage(RPMMESS_VERBOSE, "Conflicts (%d):", p->numConflict);
|
||||
while (rd) {
|
||||
if (rd->flags & RPMSENSE_CONFLICTS) {
|
||||
rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
|
||||
*namePtr++ = rd->name;
|
||||
*versionPtr++ = rd->version ? rd->version : "";
|
||||
*flagPtr++ = rd->flags & RPMSENSE_SENSEMASK;
|
||||
}
|
||||
rd = rd->next;
|
||||
}
|
||||
rpmMessage(RPMMESS_VERBOSE, "\n");
|
||||
|
||||
headerAddEntry(h, RPMTAG_CONFLICTNAME, RPM_STRING_ARRAY_TYPE,
|
||||
nameArray, p->numConflict);
|
||||
headerAddEntry(h, RPMTAG_CONFLICTVERSION, RPM_STRING_ARRAY_TYPE,
|
||||
versionArray, p->numConflict);
|
||||
headerAddEntry(h, RPMTAG_CONFLICTFLAGS, RPM_INT32_TYPE,
|
||||
flagArray, p->numConflict);
|
||||
|
||||
free(nameArray);
|
||||
free(versionArray);
|
||||
free(flagArray);
|
||||
}
|
||||
|
||||
x = p->numReq + p->numPreReq;
|
||||
if (x) {
|
||||
rd = p->reqprov;
|
||||
nameArray = namePtr = malloc(x * sizeof(*nameArray));
|
||||
versionArray = versionPtr = malloc(x * sizeof(*versionArray));
|
||||
flagArray = flagPtr = malloc(x * sizeof(*flagArray));
|
||||
rpmMessage(RPMMESS_VERBOSE, "[Pre]Requires (%d):", x);
|
||||
while (rd) {
|
||||
if (! ((rd->flags & RPMSENSE_PROVIDES) ||
|
||||
(rd->flags & RPMSENSE_OBSOLETES) ||
|
||||
(rd->flags & RPMSENSE_CONFLICTS))) {
|
||||
if (rd->flags & RPMSENSE_PREREQ) {
|
||||
rpmMessage(RPMMESS_VERBOSE, " [%s]", rd->name);
|
||||
} else {
|
||||
rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
|
||||
}
|
||||
*namePtr++ = rd->name;
|
||||
*versionPtr++ = rd->version ? rd->version : "";
|
||||
*flagPtr++ = (rd->flags & RPMSENSE_SENSEMASK) |
|
||||
(rd->flags & RPMSENSE_PREREQ);
|
||||
}
|
||||
rd = rd->next;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
1949
build/spec.c
1949
build/spec.c
File diff suppressed because it is too large
Load Diff
130
build/spec.h
130
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"
|
||||
|
||||
typedef struct SpecRec *Spec;
|
||||
#if 0
|
||||
struct ReqProvTrigger {
|
||||
int flags;
|
||||
char *name;
|
||||
char *version;
|
||||
int index; /* Only used for triggers */
|
||||
struct ReqProvTrigger *next;
|
||||
};
|
||||
#endif
|
||||
|
||||
Spec *parseSpec(FILE *f, char *specfile, char *buildRootOverride);
|
||||
void freeSpec(Spec s);
|
||||
#define RPMBUILD_ISSOURCE 1
|
||||
#define RPMBUILD_ISPATCH (1 << 1)
|
||||
#define RPMBUILD_ISICON (1 << 2)
|
||||
#define RPMBUILD_ISNO (1 << 3)
|
||||
|
||||
void dumpSpec(Spec s, FILE *f);
|
||||
#define RPMBUILD_DEFAULT_LANG "C"
|
||||
|
||||
char *getSource(Spec s, int ispatch, int num);
|
||||
char *getFullSource(Spec s, int ispatch, int num);
|
||||
struct Source {
|
||||
char *fullSource;
|
||||
char *source; /* Pointer into fullSource */
|
||||
int flags;
|
||||
int num;
|
||||
struct Source *next;
|
||||
};
|
||||
|
||||
int verifySpec(Spec s);
|
||||
struct ReadLevelEntry {
|
||||
int reading;
|
||||
struct ReadLevelEntry *next;
|
||||
};
|
||||
|
||||
struct SpecStruct {
|
||||
char *specFile;
|
||||
char *sourceRpmName;
|
||||
|
||||
FILE *file;
|
||||
char readBuf[BUFSIZ];
|
||||
char *readPtr;
|
||||
char line[BUFSIZ];
|
||||
int lineNum;
|
||||
|
||||
struct ReadLevelEntry *readStack;
|
||||
|
||||
Header buildRestrictions;
|
||||
struct SpecStruct **buildArchitectureSpecs;
|
||||
char ** buildArchitectures;
|
||||
int buildArchitectureCount;
|
||||
int inBuildArchitectures;
|
||||
|
||||
int gotBuildRoot;
|
||||
char *buildRoot;
|
||||
char *buildSubdir;
|
||||
|
||||
char *docDir;
|
||||
|
||||
char *passPhrase;
|
||||
int timeCheck;
|
||||
char *cookie;
|
||||
|
||||
struct Source *sources;
|
||||
int numSources;
|
||||
int noSource;
|
||||
|
||||
Header sourceHeader;
|
||||
int sourceCpioCount;
|
||||
struct cpioFileMapping *sourceCpioList;
|
||||
|
||||
struct MacroContext macros;
|
||||
|
||||
int autoReqProv;
|
||||
|
||||
StringBuf prep;
|
||||
StringBuf build;
|
||||
StringBuf install;
|
||||
StringBuf clean;
|
||||
|
||||
struct PackageStruct *packages;
|
||||
};
|
||||
|
||||
struct PackageStruct {
|
||||
Header header;
|
||||
|
||||
int cpioCount;
|
||||
struct cpioFileMapping *cpioList;
|
||||
|
||||
struct Source *icon;
|
||||
|
||||
int autoReqProv;
|
||||
|
||||
char *preInFile;
|
||||
char *postInFile;
|
||||
char *preUnFile;
|
||||
char *postUnFile;
|
||||
char *verifyFile;
|
||||
|
||||
StringBuf specialDoc;
|
||||
|
||||
#if 0
|
||||
struct ReqProvTrigger *triggers;
|
||||
char *triggerScripts;
|
||||
#endif
|
||||
|
||||
char *fileFile;
|
||||
StringBuf fileList; /* If NULL, package will not be written */
|
||||
|
||||
struct PackageStruct *next;
|
||||
};
|
||||
|
||||
typedef struct SpecStruct *Spec;
|
||||
typedef struct PackageStruct *Package;
|
||||
|
||||
Spec newSpec(void);
|
||||
void freeSpec(Spec spec);
|
||||
|
||||
int addSource(Spec spec, Package pkg, char *field, int tag);
|
||||
char *getSource(Spec spec, int num, int flag);
|
||||
char *getFullSource(Spec spec, int num, int flag);
|
||||
void freeSources(Spec spec);
|
||||
int parseNoSource(Spec spec, char *field, int tag);
|
||||
|
||||
#endif _SPEC_H_
|
||||
|
|
|
@ -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_
|
|
@ -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_
|
206
build/vspec.c
206
build/vspec.c
|
@ -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;
|
||||
}
|
|
@ -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))
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "rpmlib.h"
|
||||
#include "messages.h"
|
||||
|
||||
char * RPMVERSION = VERSION;
|
||||
char * RPMVERSION = VERSION; /* just to put a marker in librpm.a */
|
||||
|
||||
char ** splitString(char * str, int length, char sep) {
|
||||
char * s, * source, * dest;
|
||||
|
|
201
rpm.c
201
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;
|
||||
|
|
Loading…
Reference in New Issue