Add macro %isu_package to generate ISU Package
[platform/upstream/rpm.git] / build / build.c
index 721a4a6..81152e5 100644 (file)
 
 #include "system.h"
 
-#include <rpmio_internal.h>
-#include <rpmbuild.h>
+#include <errno.h>
+#include <sys/wait.h>
 
-static int _build_debug = 0;
+#include <rpm/rpmlog.h>
+#include <rpm/rpmfileutil.h>
+#include "build/rpmbuild_internal.h"
+#include "build/rpmbuild_misc.h"
+#include "lib/rpmug.h"
 
-static void doRmSource(Spec spec)
+#include "debug.h"
+
+/**
+ */
+static rpmRC doRmSource(rpmSpec spec)
 {
     struct Source *p;
     Package pkg;
+    int rc = 0;
     
-#if 0
-    unlink(spec->specFile);
-#endif
-
     for (p = spec->sources; p != NULL; p = p->next) {
        if (! (p->flags & RPMBUILD_ISNO)) {
-           const char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
-           unlink(fn);
-           xfree(fn);
+           char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
+           rc = unlink(fn);
+           free(fn);
+           if (rc) goto exit;
        }
     }
 
     for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
        for (p = pkg->icon; p != NULL; p = p->next) {
            if (! (p->flags & RPMBUILD_ISNO)) {
-               const char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
-               unlink(fn);
-               xfree(fn);
+               char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
+               rc = unlink(fn);
+               free(fn);
+               if (rc) goto exit;
            }
        }
     }
+exit:
+    return !rc ? RPMRC_OK : RPMRC_FAIL;
 }
 
 /*
- * The _preScript string is expanded to export values to a script environment.
+ * @todo Single use by %%doc in files.c prevents static.
  */
-/** */
-int doScript(Spec spec, int what, const char *name, StringBuf sb, int test)
+rpmRC doScript(rpmSpec spec, rpmBuildFlags what, const char *name,
+               const char *sb, int test)
 {
-    const char * rootURL = spec->rootURL;
-    const char * rootDir;
-    const char *scriptName = NULL;
-    const char * buildDirURL = rpmGenPath(rootURL, "%{_builddir}", "");
-    const char * buildScript;
-    const char * buildCmd = NULL;
-    const char * buildTemplate = NULL;
-    const char * buildPost = NULL;
+    char *scriptName = NULL;
+    char * buildDir = rpmGenPath(spec->rootDir, "%{_builddir}", "");
+    char * buildCmd = NULL;
+    char * buildTemplate = NULL;
+    char * buildPost = NULL;
     const char * mTemplate = NULL;
+    const char * mCmd = NULL;
     const char * mPost = NULL;
     int argc = 0;
     const char **argv = NULL;
     FILE * fp = NULL;
-    urlinfo u = NULL;
 
-    FD_t fd;
-    FD_t xfd;
-    int child;
+    FD_t fd = NULL;
+    pid_t pid;
+    pid_t child;
     int status;
-    int rc;
+    rpmRC rc = RPMRC_FAIL; /* assume failure */
     
     switch (what) {
-      case RPMBUILD_PREP:
-       name = "%prep";
-       sb = spec->prep;
+    case RPMBUILD_PREP:
        mTemplate = "%{__spec_prep_template}";
        mPost = "%{__spec_prep_post}";
+       mCmd = "%{__spec_prep_cmd}";
        break;
-      case RPMBUILD_BUILD:
-       name = "%build";
-       sb = spec->build;
+    case RPMBUILD_BUILD:
        mTemplate = "%{__spec_build_template}";
        mPost = "%{__spec_build_post}";
+       mCmd = "%{__spec_build_cmd}";
        break;
-      case RPMBUILD_INSTALL:
-       name = "%install";
-       sb = spec->install;
+    case RPMBUILD_INSTALL:
        mTemplate = "%{__spec_install_template}";
        mPost = "%{__spec_install_post}";
+       mCmd = "%{__spec_install_cmd}";
+       break;
+    case RPMBUILD_CHECK:
+       mTemplate = "%{__spec_check_template}";
+       mPost = "%{__spec_check_post}";
+       mCmd = "%{__spec_check_cmd}";
        break;
-      case RPMBUILD_CLEAN:
-       name = "%clean";
-       sb = spec->clean;
+    case RPMBUILD_CLEAN:
        mTemplate = "%{__spec_clean_template}";
        mPost = "%{__spec_clean_post}";
+       mCmd = "%{__spec_clean_cmd}";
        break;
-      case RPMBUILD_RMBUILD:
-       name = "--clean";
+    case RPMBUILD_RMBUILD:
        mTemplate = "%{__spec_clean_template}";
        mPost = "%{__spec_clean_post}";
+       mCmd = "%{__spec_clean_cmd}";
        break;
-      case RPMBUILD_STRINGBUF:
-      default:
+    case RPMBUILD_STRINGBUF:
+    default:
        mTemplate = "%{___build_template}";
        mPost = "%{___build_post}";
+       mCmd = "%{___build_cmd}";
        break;
     }
 
     if ((what != RPMBUILD_RMBUILD) && sb == NULL) {
-       rc = 0;
+       rc = RPMRC_OK;
        goto exit;
     }
     
-    if (makeTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) {
-       rpmError(RPMERR_SCRIPT, _("Unable to open temp file."));
-       rc = RPMERR_SCRIPT;
+    fd = rpmMkTempFile(spec->rootDir, &scriptName);
+    if (Ferror(fd)) {
+       rpmlog(RPMLOG_ERR, _("Unable to open temp file: %s\n"), Fstrerror(fd));
        goto exit;
     }
 
-#ifdef HAVE_FCHMOD
-    switch (rootut) {
-    case URL_IS_PATH:
-    case URL_IS_UNKNOWN:
-       (void)fchmod(Fileno(fd), 0600);
-       break;
-    default:
-       break;
-    }
-#endif
-
-    if (fdGetFp(fd) == NULL)
-       xfd = Fdopen(fd, "w.fpio");
-    else
-       xfd = fd;
-    if ((fp = fdGetFp(xfd)) == NULL) {
-       rc = RPMERR_SCRIPT;
+    if ((fp = fdopen(Fileno(fd), "w")) == NULL) {
+       rpmlog(RPMLOG_ERR, _("Unable to open stream: %s\n"), strerror(errno));
        goto exit;
     }
     
-    (void) urlPath(rootURL, &rootDir);
-    if (*rootDir == '\0') rootDir = "/";
-
-    (void) urlPath(scriptName, &buildScript);
-
     buildTemplate = rpmExpand(mTemplate, NULL);
     buildPost = rpmExpand(mPost, NULL);
 
-    fputs(buildTemplate, fp);
+    (void) fputs(buildTemplate, fp);
 
     if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir)
-       fprintf(fp, "cd %s\n", spec->buildSubdir);
+       fprintf(fp, "cd '%s'\n", spec->buildSubdir);
 
     if (what == RPMBUILD_RMBUILD) {
        if (spec->buildSubdir)
-           fprintf(fp, "rm -rf %s\n", spec->buildSubdir);
-    } else
-       fprintf(fp, "%s", getStringBuf(sb));
+           fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir);
+    } else if (sb != NULL)
+       fprintf(fp, "%s", sb);
 
-    fputs(buildPost, fp);
-    
-    Fclose(xfd);
+    (void) fputs(buildPost, fp);
+    (void) fclose(fp);
 
     if (test) {
-       rc = 0;
+       rc = RPMRC_OK;
        goto exit;
     }
     
-if (_build_debug)
-fprintf(stderr, "*** rootURL %s buildDirURL %s\n", rootURL, buildDirURL);
-    if (buildDirURL && buildDirURL[0] != '/' &&
-       (urlSplit(buildDirURL, &u) != 0)) {
-       rc = RPMERR_SCRIPT;
+    if (buildDir && buildDir[0] != '/') {
        goto exit;
     }
-    if (u) {
-       switch (u->urltype) {
-       case URL_IS_FTP:
-if (_build_debug)
-fprintf(stderr, "*** addMacros\n");
-           addMacro(spec->macros, "_remsh", NULL, "%{__remsh}", RMIL_SPEC);
-           addMacro(spec->macros, "_remhost", NULL, u->host, RMIL_SPEC);
-           if (strcmp(rootDir, "/"))
-               addMacro(spec->macros, "_remroot", NULL, rootDir, RMIL_SPEC);
-           break;
-       case URL_IS_HTTP:
-       default:
-           break;
-       }
-    }
 
-    buildCmd = rpmExpand("%{___build_cmd}", " ", buildScript, NULL);
-    poptParseArgvString(buildCmd, &argc, &argv);
+    buildCmd = rpmExpand(mCmd, " ", scriptName, NULL);
+    (void) poptParseArgvString(buildCmd, &argc, &argv);
 
-    rpmMessage(RPMMESS_NORMAL, _("Executing(%s): %s\n"), name, buildCmd);
+    rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd);
     if (!(child = fork())) {
-
        errno = 0;
-       execvp(argv[0], (char *const *)argv);
+       (void) execvp(argv[0], (char *const *)argv);
 
-       rpmError(RPMERR_SCRIPT, _("Exec of %s failed (%s): %s"), scriptName, name, strerror(errno));
+       rpmlog(RPMLOG_ERR, _("Exec of %s failed (%s): %s\n"),
+               scriptName, name, strerror(errno));
 
-       _exit(-1);
+       _exit(127); /* exit 127 for compatibility with bash(1) */
     }
 
-    rc = waitpid(child, &status, 0);
+    pid = waitpid(child, &status, 0);
+
+    if (pid == -1) {
+       rpmlog(RPMLOG_ERR, _("Error executing scriptlet %s (%s)\n"),
+                scriptName, name);
+       goto exit;
+    }
 
     if (!WIFEXITED(status) || WEXITSTATUS(status)) {
-       rpmError(RPMERR_SCRIPT, _("Bad exit status from %s (%s)"),
+       rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"),
                 scriptName, name);
-       rc = RPMERR_SCRIPT;
     } else
-       rc = 0;
+       rc = RPMRC_OK;
     
 exit:
+    Fclose(fd);
     if (scriptName) {
-       if (!rc)
-           Unlink(scriptName);
-       xfree(scriptName);
-    }
-    if (u) {
-       switch (u->urltype) {
-       case URL_IS_FTP:
-       case URL_IS_HTTP:
-if (_build_debug)
-fprintf(stderr, "*** delMacros\n");
-           delMacro(spec->macros, "_remsh");
-           delMacro(spec->macros, "_remhost");
-           if (strcmp(rootDir, "/"))
-               delMacro(spec->macros, "_remroot");
-           break;
-       default:
-           break;
-       }
+       if (rc == RPMRC_OK && !rpmIsDebug())
+           (void) unlink(scriptName);
+       free(scriptName);
     }
-    FREE(argv);
-    FREE(buildCmd);
-    FREE(buildTemplate);
-    FREE(buildDirURL);
+    free(argv);
+    free(buildCmd);
+    free(buildTemplate);
+    free(buildPost);
+    free(buildDir);
 
     return rc;
 }
 
-/** */
-int buildSpec(Spec spec, int what, int test)
+static rpmRC buildSpec(BTA_t buildArgs, rpmSpec spec, int what)
 {
-    int x, rc;
+    rpmRC rc = RPMRC_OK;
+    int test = (what & RPMBUILD_NOBUILD);
+    char *cookie = buildArgs->cookie ? xstrdup(buildArgs->cookie) : NULL;
+
+    if (rpmExpandNumeric("%{?source_date_epoch_from_changelog}") &&
+       getenv("SOURCE_DATE_EPOCH") == NULL) {
+       /* Use date of first (== latest) changelog entry */
+       Header h = spec->packages->header;
+       struct rpmtd_s td;
+       if (headerGet(h, RPMTAG_CHANGELOGTIME, &td, (HEADERGET_MINMEM|HEADERGET_RAW))) {
+           char sdestr[22];
+           snprintf(sdestr, sizeof(sdestr), "%lli",
+                    (long long) rpmtdGetNumber(&td));
+           rpmlog(RPMLOG_NOTICE, _("setting %s=%s\n"), "SOURCE_DATE_EPOCH", sdestr);
+           setenv("SOURCE_DATE_EPOCH", sdestr, 0);
+           rpmtdFreeData(&td);
+       }
+    }
 
-    if (!spec->inBuildArchitectures && spec->buildArchitectureCount) {
-       /* When iterating over buildArchitectures, do the source    */
+    /* XXX TODO: rootDir is only relevant during build, eliminate from spec */
+    spec->rootDir = buildArgs->rootdir;
+    if (!spec->recursing && spec->BACount) {
+       int x;
+       /* When iterating over BANames, do the source    */
        /* packaging on the first run, and skip RMSOURCE altogether */
-       for (x = 0; x < spec->buildArchitectureCount; x++) {
-           if ((rc = buildSpec(spec->buildArchitectureSpecs[x],
+       if (spec->BASpecs != NULL)
+       for (x = 0; x < spec->BACount; x++) {
+           if ((rc = buildSpec(buildArgs, spec->BASpecs[x],
                                (what & ~RPMBUILD_RMSOURCE) |
-                               (x ? 0 : (what & RPMBUILD_PACKAGESOURCE)),
-                               test))) {
-               return rc;
+                               (x ? 0 : (what & RPMBUILD_PACKAGESOURCE))))) {
+               goto exit;
            }
        }
     } else {
+       int didBuild = (what & (RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL));
+
        if ((what & RPMBUILD_PREP) &&
-           (rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test)))
-               return rc;
+           (rc = doScript(spec, RPMBUILD_PREP, "%prep",
+                          getStringBuf(spec->prep), test)))
+               goto exit;
 
        if ((what & RPMBUILD_BUILD) &&
-           (rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test)))
-               return rc;
+           (rc = doScript(spec, RPMBUILD_BUILD, "%build",
+                          getStringBuf(spec->build), test)))
+               goto exit;
 
        if ((what & RPMBUILD_INSTALL) &&
-           (rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test)))
-               return rc;
+           (rc = doScript(spec, RPMBUILD_INSTALL, "%install",
+                          getStringBuf(spec->install), test)))
+               goto exit;
+
+       if ((what & RPMBUILD_CHECK) &&
+           (rc = doScript(spec, RPMBUILD_CHECK, "%check",
+                          getStringBuf(spec->check), test)))
+               goto exit;
 
        if ((what & RPMBUILD_PACKAGESOURCE) &&
-           (rc = processSourceFiles(spec)))
-               return rc;
+           (rc = processSourceFiles(spec, buildArgs->pkgFlags)))
+               goto exit;
 
        if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
            (what & RPMBUILD_FILECHECK)) &&
-           (rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL, test)))
-               return rc;
+           (rc = processBinaryFiles(spec, buildArgs->pkgFlags,
+                                    what & RPMBUILD_INSTALL, test)))
+               goto exit;
+
+       if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY)) &&
+           (rc = processBinaryPolicies(spec, test)))
+               goto exit;
 
        if (((what & RPMBUILD_PACKAGESOURCE) && !test) &&
-           (rc = packageSources(spec)))
+           (rc = packageSources(spec, &cookie)))
                return rc;
 
        if (((what & RPMBUILD_PACKAGEBINARY) && !test) &&
-           (rc = packageBinaries(spec)))
-               return rc;
+           (rc = packageBinaries(spec, cookie, (didBuild == 0))))
+               goto exit;
        
        if ((what & RPMBUILD_CLEAN) &&
-           (rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test)))
-               return rc;
+           (rc = doScript(spec, RPMBUILD_CLEAN, "%clean",
+                          getStringBuf(spec->clean), test)))
+               goto exit;
 
        if ((what & RPMBUILD_RMBUILD) &&
-           (rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test)))
-               return rc;
+           (rc = doScript(spec, RPMBUILD_RMBUILD, "--clean", NULL, test)))
+               goto exit;
     }
 
     if (what & RPMBUILD_RMSOURCE)
        doRmSource(spec);
 
     if (what & RPMBUILD_RMSPEC)
-       unlink(spec->specFile);
+       (void) unlink(spec->specFile);
 
-    return 0;
+exit:
+    free(cookie);
+    spec->rootDir = NULL;
+    if (rc != RPMRC_OK && rpmlogGetNrecs() > 0) {
+       rpmlog(RPMLOG_NOTICE, _("\n\nRPM build errors:\n"));
+       rpmlogPrint(NULL);
+    }
+    rpmugFree();
+
+    return rc;
+}
+
+rpmRC rpmSpecBuild(rpmSpec spec, BTA_t buildArgs)
+{
+    /* buildSpec() can recurse with different buildAmount, pass it separately */
+    return buildSpec(buildArgs, spec, buildArgs->buildAmount);
 }