- Main Page
- Related Pages
- Modules
- Data Structures
- Files

# build.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006
    00007 #include <libgen.h>
    00008
    00009 #include <rpm/rpmcli.h>
    00010 #include <rpm/rpmtag.h>
    00011 #include <rpm/rpmlib.h>         /* rpmrc, MACHTABLE .. */
    00012 #include <rpm/rpmbuild.h>
    00013
    00014 #include <rpm/rpmps.h>
    00015 #include <rpm/rpmte.h>
    00016 #include <rpm/rpmts.h>
    00017 #include <rpm/rpmfileutil.h>
    00018 #include <rpm/rpmlog.h>
    00019
    00020 #include "build.h"
    00021 #include "debug.h"
    00022
    00025 static int checkSpec(rpmts ts, Header h)
    00026 {
    00027     rpmps ps;
    00028     int rc;
    00029
    00030     if (!headerIsEntry(h, RPMTAG_REQUIRENAME)
    00031      && !headerIsEntry(h, RPMTAG_CONFLICTNAME))
    00032         return 0;
    00033
    00034     rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
    00035
    00036     rc = rpmtsCheck(ts);
    00037
    00038     ps = rpmtsProblems(ts);
    00039     if (rc == 0 && rpmpsNumProblems(ps) > 0) {
    00040         rpmlog(RPMLOG_ERR, _("Failed build dependencies:\n"));
    00041         rpmpsPrint(NULL, ps);
    00042         rc = 1;
    00043     }
    00044     ps = rpmpsFree(ps);
    00045
    00046     /* XXX nuke the added package. */
    00047     rpmtsClean(ts);
    00048
    00049     return rc;
    00050 }
    00051
    00054 static int isSpecFile(const char * specfile)
    00055 {
    00056     char buf[256];
    00057     const char * s;
    00058     FILE * f;
    00059     int count;
    00060     int checking;
    00061
    00062     f = fopen(specfile, "r");
    00063     if (f == NULL || ferror(f)) {
    00064         rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"),
    00065                 specfile, strerror(errno));
    00066         return 0;
    00067     }
    00068     count = fread(buf, sizeof(buf[0]), sizeof(buf), f);
    00069     (void) fclose(f);
    00070
    00071     if (count == 0)
    00072         return 0;
    00073
    00074     checking = 1;
    00075     for (s = buf; count--; s++) {
    00076         switch (*s) {
    00077         case '\r':
    00078         case '\n':
    00079             checking = 1;
    00080             break;
    00081         case ':':
    00082             checking = 0;
    00083             break;
    00084         default:
    00085 #if 0
    00086             if (checking && !(isprint(*s) || isspace(*s))) return 0;
    00087             break;
    00088 #else
    00089             if (checking && !(isprint(*s) || isspace(*s)) && *(unsigned char *)s < 32) return 0;
    00090             break;
    00091 #endif
    00092         }
    00093     }
    00094     return 1;
    00095 }
    00096
    00097 /*
    00098  * Try to find a spec from a tarball pointed to by arg.
    00099  * Return absolute path to spec name on success, otherwise NULL.
    00100  */
    00101 static char * getTarSpec(const char *arg)
    00102 {
    00103     char *specFile = NULL;
    00104     char *specDir;
    00105     char *specBase;
    00106     char *tmpSpecFile;
    00107     const char **try;
    00108     char tarbuf[BUFSIZ];
    00109     int gotspec = 0, res;
    00110     static const char *tryspec[] = { "Specfile", "\\*.spec", NULL };
    00111
    00112     specDir = rpmGetPath("%{_specdir}", NULL);
    00113     tmpSpecFile = rpmGetPath("%{_specdir}/", "rpm-spec.XXXXXX", NULL);
    00114
    00115     (void) close(mkstemp(tmpSpecFile));
    00116
    00117     for (try = tryspec; *try != NULL; try++) {
    00118         FILE *fp;
    00119         char *cmd;
    00120
    00121         cmd = rpmExpand("%{uncompress: ", arg, "} | ",
    00122                         "%{__tar} xOvf - --wildcards ", *try,
    00123                         " 2>&1 > ", tmpSpecFile, NULL);
    00124
    00125         if (!(fp = popen(cmd, "r"))) {
    00126             rpmlog(RPMLOG_ERR, _("Failed to open tar pipe: %m\n"));
    00127         } else {
    00128             char *fok = fgets(tarbuf, sizeof(tarbuf) - 1, fp);
    00129             pclose(fp);
    00130             gotspec = (fok != NULL) && isSpecFile(tmpSpecFile);
    00131         }
    00132
    00133         if (!gotspec)
    00134             unlink(tmpSpecFile);
    00135         free(cmd);
    00136     }
    00137
    00138     if (!gotspec) {
    00139         rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg);
    00140         goto exit;
    00141     }
    00142
    00143     specBase = basename(tarbuf);
    00144     /* remove trailing \n */
    00145     specBase[strlen(specBase)-1] = '\0';
    00146
    00147     rasprintf(&specFile, "%s/%s", specDir, specBase);
    00148     res = rename(tmpSpecFile, specFile);
    00149
    00150     if (res) {
    00151         rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"),
    00152                 tmpSpecFile, specFile);
    00153         free(specFile);
    00154         specFile = NULL;
    00155     } else {
    00156         /* mkstemp() can give unnecessarily strict permissions, fixup */
    00157         mode_t mask;
    00158         umask(mask = umask(0));
    00159         (void) chmod(specFile, 0666 & ~mask);
    00160     }
    00161
    00162 exit:
    00163     (void) unlink(tmpSpecFile);
    00164     free(tmpSpecFile);
    00165     free(specDir);
    00166     return specFile;
    00167 }
    00168
    00171 static int buildForTarget(rpmts ts, const char * arg, BTA_t ba)
    00172 {
    00173     const char * passPhrase = ba->passPhrase;
    00174     const char * cookie = ba->cookie;
    00175     int buildAmount = ba->buildAmount;
    00176     char * buildRootURL = NULL;
    00177     char * specFile = NULL;
    00178     rpmSpec spec = NULL;
    00179     int rc = 1; /* assume failure */
    00180
    00181     ba = NULL;
    00182
    00183 #ifndef DYING
    00184     rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
    00185 #endif
    00186
    00187     if (ba->buildRootOverride)
    00188         buildRootURL = rpmGenPath(NULL, ba->buildRootOverride, NULL);
    00189
    00190     if (ba->buildMode == 't') {
    00191         char *srcdir = NULL, *dir;
    00192
    00193         specFile = getTarSpec(arg);
    00194         if (!specFile)
    00195             goto exit;
    00196
    00197         /* Make the directory of the tarball %_sourcedir for this run */
    00198         /* dirname() may modify contents so extra hoops needed. */
    00199         if (*arg != '/') {
    00200             srcdir = dir = rpmGetCwd();
    00201         } else {
    00202             dir = xstrdup(arg);
    00203             srcdir = dirname(dir);
    00204         }
    00205         addMacro(NULL, "_sourcedir", NULL, srcdir, RMIL_TARBALL);
    00206         free(dir);
    00207     } else {
    00208         specFile = xstrdup(arg);
    00209     }
    00210
    00211     if (*specFile != '/') {
    00212         char *cwd = rpmGetCwd();
    00213         char *s = NULL;
    00214         rasprintf(&s, "%s/%s", cwd, arg);
    00215         free(specFile);
    00216         specFile = s;
    00217     }
    00218
    00219     struct stat st;
    00220     if (stat(specFile, &st) < 0) {
    00221         rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specFile);
    00222         goto exit;
    00223     }
    00224     if (! S_ISREG(st.st_mode)) {
    00225         rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"), specFile);
    00226         goto exit;
    00227     }
    00228
    00229     /* Try to verify that the file is actually a specfile */
    00230     if (!isSpecFile(specFile)) {
    00231         rpmlog(RPMLOG_ERR,
    00232                 _("File %s does not appear to be a specfile.\n"), specFile);
    00233         goto exit;
    00234     }
    00235
    00236     /* Parse the spec file */
    00237 #define _anyarch(_f)    \
    00238 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
    00239     if (parseSpec(ts, specFile, ba->rootdir, buildRootURL, 0, passPhrase,
    00240                 cookie, _anyarch(buildAmount), ba->force))
    00241     {
    00242         goto exit;
    00243     }
    00244 #undef  _anyarch
    00245     if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
    00246         goto exit;
    00247     }
    00248
    00249     /* Assemble source header from parsed components */
    00250     initSourceHeader(spec);
    00251
    00252     /* Check build prerequisites */
    00253     if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
    00254         goto exit;
    00255     }
    00256
    00257     if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
    00258         goto exit;
    00259     }
    00260
    00261     if (ba->buildMode == 't')
    00262         (void) unlink(specFile);
    00263     rc = 0;
    00264
    00265 exit:
    00266     free(specFile);
    00267     freeSpec(spec);
    00268     free(buildRootURL);
    00269     return rc;
    00270 }
    00271
    00272 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile)
    00273 {
    00274     char *t, *te;
    00275     int rc = 0;
    00276     char * targets = ba->targets;
    00277 #define buildCleanMask  (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
    00278     int cleanFlags = ba->buildAmount & buildCleanMask;
    00279     rpmVSFlags vsflags, ovsflags;
    00280
    00281     vsflags = rpmExpandNumeric("%{_vsflags_build}");
    00282     if (ba->qva_flags & VERIFY_DIGEST)
    00283         vsflags |= _RPMVSF_NODIGESTS;
    00284     if (ba->qva_flags & VERIFY_SIGNATURE)
    00285         vsflags |= _RPMVSF_NOSIGNATURES;
    00286     if (ba->qva_flags & VERIFY_HDRCHK)
    00287         vsflags |= RPMVSF_NOHDRCHK;
    00288     ovsflags = rpmtsSetVSFlags(ts, vsflags);
    00289
    00290     if (targets == NULL) {
    00291         rc =  buildForTarget(ts, arg, ba);
    00292         goto exit;
    00293     }
    00294
    00295     /* parse up the build operators */
    00296
    00297     printf(_("Building target platforms: %s\n"), targets);
    00298
    00299     ba->buildAmount &= ~buildCleanMask;
    00300     for (t = targets; *t != '\0'; t = te) {
    00301         char *target;
    00302         if ((te = strchr(t, ',')) == NULL)
    00303             te = t + strlen(t);
    00304         target = xmalloc(te-t+1);
    00305         strncpy(target, t, (te-t));
    00306         target[te-t] = '\0';
    00307         if (*te != '\0')
    00308             te++;
    00309         else    /* XXX Perform clean-up after last target build. */
    00310             ba->buildAmount |= cleanFlags;
    00311
    00312         printf(_("Building for target %s\n"), target);
    00313
    00314         /* Read in configuration for target. */
    00315         rpmFreeMacros(NULL);
    00316         rpmFreeRpmrc();
    00317         (void) rpmReadConfigFiles(rcfile, target);
    00318         free(target);
    00319         rc = buildForTarget(ts, arg, ba);
    00320         if (rc)
    00321             break;
    00322     }
    00323
    00324 exit:
    00325     vsflags = rpmtsSetVSFlags(ts, ovsflags);
    00326     /* Restore original configuration. */
    00327     rpmFreeMacros(NULL);
    00328     rpmFreeRpmrc();
    00329     (void) rpmReadConfigFiles(rcfile, NULL);
    00330
    00331     return rc;
    00332 }