diff --git a/build/parseList.c b/build/parseList.c index c382cbc6bb..529ba12c96 100644 --- a/build/parseList.c +++ b/build/parseList.c @@ -8,13 +8,124 @@ #include "build/rpmbuild_internal.h" #include "debug.h" +static int addLinesFromFile(rpmSpec spec, const char * const fn, rpmTagVal tag) +{ + char buf[PATH_MAX+1]; + char *expanded; + FILE *f; + int res = -1; + int lineno = 0, nlines = 0; + + f = fopen(fn, "r"); + if (f == NULL) + return -1; + + buf[PATH_MAX] = '\0'; + + while (fgets(buf, sizeof(buf), f)) { + char *c; + lineno++; + + c = strrchr(buf, '\n'); + if (c) + *c = '\0'; + + if (handleComments(buf)) + continue; + if (specExpand(spec, lineno, buf, &expanded)) + goto exit; + + addSource(spec, 0, expanded, tag); + free(expanded); + nlines++; + } + + if (nlines == 0) { + int terminate = + rpmExpandNumeric(tag == RPMTAG_SOURCE + ? "%{?_empty_sourcelist_terminate_build}" + : "%{?_empyy_patchlist_terminate_build}"); + rpmlog(terminate ? RPMLOG_ERR : RPMLOG_WARNING, + _("Empty %s file %s\n"), + tag == RPMTAG_SOURCE ? "%sourcelist" : "%patchlist", + fn); + if (terminate) + goto exit; + } + + if (ferror(f)) + rpmlog(RPMLOG_ERR, _("Error reading %s file %s: %m\n"), + tag == RPMTAG_SOURCE ? "%sourcelist" : "%patchlist", + fn); + else + res = 0; + +exit: + fclose(f); + return res; +} int parseList(rpmSpec spec, const char *name, rpmTagVal tag) { int res = PART_ERROR; ARGV_t lst = NULL; + int rc, argc = 0; + int arg; + const char **argv = NULL; + poptContext optCon = NULL; + struct poptOption optionsTable[] = { + { NULL, 'f', POPT_ARG_STRING, NULL, 'f', NULL, NULL}, + { 0, 0, 0, 0, 0, NULL, NULL} + }; + char * file = NULL; + + if ((rc = poptParseArgvString(spec->line, &argc, &argv))) { + rpmlog(RPMLOG_ERR, _("line %d: Error parsing %%%s: %s\n"), + spec->lineNum, name, poptStrerror(rc)); + goto exit; + } + + optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); + while ((arg = poptGetNextOpt(optCon)) > 0) { + ; + } + + if (arg < -1) { + rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"), + spec->lineNum, + poptBadOption(optCon, POPT_BADOPTION_NOALIAS), + spec->line); + goto exit; + } + + lst = argvNew(); + + for (arg = 1; arg < argc; arg++) { + if (rstreq(argv[arg], "-f")) { + + if (!argv[arg+1]) { + rpmlog(RPMLOG_ERR, + _("line %d: \"%%%s -f\" requires an argument.\n"), + spec->lineNum, name); + goto exit; + } + + addSource(spec, 0, argv[arg+1], RPMTAG_SOURCE); + + if (argv[arg+1][0] == '/') + file = rpmGetPath(argv[arg+1], NULL); + else + file = rpmGetPath("%{_sourcedir}/", argv[arg+1], NULL); + + res = addLinesFromFile(spec, file, tag); + if (res < 0) { + rpmlog(RPMLOG_ERR, _("line %d: %%%s: Error parsing %s\n"), + spec->lineNum, name, argv[arg+1]); + goto exit; + } + } + } - /* There are no options to %patchlist and %sourcelist */ if ((res = parseLines(spec, (STRIP_TRAILINGSPACE | STRIP_COMMENTS), &lst, NULL)) == PART_ERROR) { goto exit; @@ -27,6 +138,9 @@ int parseList(rpmSpec spec, const char *name, rpmTagVal tag) } exit: + free(file); argvFree(lst); + free(argv); + poptFreeContext(optCon); return res; } diff --git a/macros.in b/macros.in index fe9803aad3..f7c405c8c0 100644 --- a/macros.in +++ b/macros.in @@ -442,6 +442,16 @@ package or when debugging this package.\ # Note: The default value should be 0 for legacy compatibility. %_empty_manifest_terminate_build 1 +# +# Should empty %sourcelist file terminate a build? +# +%_empty_sourcelist_terminate_build 1 + +# +# Should empty %patchlist file terminate a build? +# +%_empty_patchlist_terminate_build 1 + # # Should binaries in noarch packages terminate a build? %_binaries_in_noarch_packages_terminate_build 1 diff --git a/system.h b/system.h index 570cef13a4..8078473a8d 100644 --- a/system.h +++ b/system.h @@ -126,5 +126,6 @@ extern int fdatasync(int fildes); #include "misc/fnmatch.h" #include +#include #endif /* H_SYSTEM */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 38121eda1e..57138f7c58 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -98,6 +98,8 @@ EXTRA_DIST += data/RPMS/hello-2.0-1.x86_64-signed.rpm EXTRA_DIST += data/SRPMS/foo-1.0-1.src.rpm EXTRA_DIST += data/SRPMS/hello-1.0-1.src.rpm EXTRA_DIST += data/SOURCES/hello.c +EXTRA_DIST += data/SOURCES/patchlist +EXTRA_DIST += data/SPECS/hello-patchlist-f.spec EXTRA_DIST += data/SPECS/hello-attr-buildid.spec EXTRA_DIST += data/SPECS/hello-config-buildid.spec EXTRA_DIST += data/SPECS/hello-cd.spec diff --git a/tests/data/SOURCES/patchlist b/tests/data/SOURCES/patchlist new file mode 100644 index 0000000000..f11d44196b --- /dev/null +++ b/tests/data/SOURCES/patchlist @@ -0,0 +1,2 @@ +hello-1.0-modernize.patch +hello-1.0-install.patch diff --git a/tests/data/SPECS/hello-patchlist-f.spec b/tests/data/SPECS/hello-patchlist-f.spec new file mode 100644 index 0000000000..93c555c1f7 --- /dev/null +++ b/tests/data/SPECS/hello-patchlist-f.spec @@ -0,0 +1,30 @@ +Name: hello +Version: 1.0 +Release: 1 +Group: Testing +License: GPL +Summary: Simple rpm demonstration. + +%sourcelist +hello-1.0.tar.gz + +%patchlist -f patchlist + +%description +Simple rpm demonstration. + +%prep +%setup -q +%patch0 -p1 -b .modernize +%patch1 -p1 -b .install + +%build +%make_build CFLAGS="$RPM_OPT_FLAGS" + +%install +%make_install + +%files +%doc FAQ +/usr/local/bin/hello + diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at index 4b4ee51da2..986baaca6f 100644 --- a/tests/rpmbuild.at +++ b/tests/rpmbuild.at @@ -51,6 +51,24 @@ run rpmbuild \ [ignore], [ignore]) AT_CLEANUP + +# ------------------------------ +# Check if patchlist -f works +AT_SETUP([rpmbuild -ba patchlist -f]) +AT_KEYWORDS([build]) +AT_CHECK([ +rm -rf ${TOPDIR} +AS_MKDIR_P(${TOPDIR}/SOURCES) + +cp "${abs_srcdir}"/data/SOURCES/hello-1.0.tar.gz "${abs_srcdir}"/data/SOURCES/hello-1.0-*.patch "${abs_srcdir}"/data/SOURCES/patchlist ${TOPDIR}/SOURCES +run rpmbuild \ + -ba "${abs_srcdir}"/data/SPECS/hello-patchlist-f.spec +], +[0], +[ignore], +[ignore]) +AT_CLEANUP + # ------------------------------ # Check if rpmbuild --rebuild *.src.rpm works AT_SETUP([rpmbuild --rebuild])