- 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 #include <lib/misc.h>
    00020
    00021 #include "build.h"
    00022 #include "debug.h"
    00023
    00026 static int checkSpec(rpmts ts, Header h)
    00027 {
    00028     rpmps ps;
    00029     int rc;
    00030
    00031     if (!headerIsEntry(h, RPMTAG_REQUIRENAME)
    00032      && !headerIsEntry(h, RPMTAG_CONFLICTNAME))
    00033         return 0;
    00034
    00035     rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
    00036
    00037     rc = rpmtsCheck(ts);
    00038
    00039     ps = rpmtsProblems(ts);
    00040     if (rc == 0 && rpmpsNumProblems(ps) > 0) {
    00041         rpmlog(RPMLOG_ERR, _("Failed build dependencies:\n"));
    00042         rpmpsPrint(NULL, ps);
    00043         rc = 1;
    00044     }
    00045     ps = rpmpsFree(ps);
    00046
    00047     /* XXX nuke the added package. */
    00048     rpmtsClean(ts);
    00049
    00050     return rc;
    00051 }
    00052
    00055 static int isSpecFile(const char * specfile)
    00056 {
    00057     char buf[256];
    00058     const char * s;
    00059     FILE * f;
    00060     int count;
    00061     int checking;
    00062
    00063     f = fopen(specfile, "r");
    00064     if (f == NULL || ferror(f)) {
    00065         rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"),
    00066                 specfile, strerror(errno));
    00067         return 0;
    00068     }
    00069     count = fread(buf, sizeof(buf[0]), sizeof(buf), f);
    00070     (void) fclose(f);
    00071
    00072     if (count == 0)
    00073         return 0;
    00074
    00075     checking = 1;
    00076     for (s = buf; count--; s++) {
    00077         switch (*s) {
    00078         case '\r':
    00079         case '\n':
    00080             checking = 1;
    00081             break;
    00082         case ':':
    00083             checking = 0;
    00084             break;
    00085         default:
    00086 #if 0
    00087             if (checking && !(isprint(*s) || isspace(*s))) return 0;
    00088             break;
    00089 #else
    00090             if (checking && !(isprint(*s) || isspace(*s)) && *(unsigned char *)s < 32) return 0;
    00091             break;
    00092 #endif
    00093         }
    00094     }
    00095     return 1;
    00096 }
    00097
    00098 /*
    00099  * Try to find a spec from a tarball pointed to by arg.
    00100  * Return absolute path to spec name on success, otherwise NULL.
    00101  */
    00102 static char * getTarSpec(const char *arg)
    00103 {
    00104     char *specFile = NULL;
    00105     char *specDir;
    00106     char *specBase;
    00107     char *tmpSpecFile;
    00108     const char **try;
    00109     char tarbuf[BUFSIZ];
    00110     int gotspec = 0, res;
    00111     static const char *tryspec[] = { "Specfile", "\\*.spec", NULL };
    00112
    00113     specDir = rpmGetPath("%{_specdir}", NULL);
    00114     tmpSpecFile = rpmGetPath("%{_specdir}/", "rpm-spec.XXXXXX", NULL);
    00115
    00116     (void) close(mkstemp(tmpSpecFile));
    00117
    00118     for (try = tryspec; *try != NULL; try++) {
    00119         FILE *fp;
    00120         char *cmd;
    00121
    00122         cmd = rpmExpand("%{uncompress: ", arg, "} | ",
    00123                         "%{__tar} xOvf - --wildcards ", *try,
    00124                         " 2>&1 > ", tmpSpecFile, NULL);
    00125
    00126         if (!(fp = popen(cmd, "r"))) {
    00127             rpmlog(RPMLOG_ERR, _("Failed to open tar pipe: %m\n"));
    00128         } else {
    00129             char *fok = fgets(tarbuf, sizeof(tarbuf) - 1, fp);
    00130             pclose(fp);
    00131             gotspec = (fok != NULL) && isSpecFile(tmpSpecFile);
    00132         }
    00133
    00134         if (!gotspec)
    00135             unlink(tmpSpecFile);
    00136         free(cmd);
    00137     }
    00138
    00139     if (!gotspec) {
    00140         rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg);
    00141         goto exit;
    00142     }
    00143
    00144     specBase = basename(tarbuf);
    00145     /* remove trailing \n */
    00146     specBase[strlen(specBase)-1] = '\0';
    00147
    00148     rasprintf(&specFile, "%s/%s", specDir, specBase);
    00149     res = rename(tmpSpecFile, specFile);
    00150
    00151     if (res) {
    00152         rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"),
    00153                 tmpSpecFile, specFile);
    00154         free(specFile);
    00155         specFile = NULL;
    00156     } else {
    00157         /* mkstemp() can give unnecessarily strict permissions, fixup */
    00158         mode_t mask;
    00159         umask(mask = umask(0));
    00160         (void) chmod(specFile, 0666 & ~mask);
    00161     }
    00162
    00163 exit:
    00164     (void) unlink(tmpSpecFile);
    00165     free(tmpSpecFile);
    00166     free(specDir);
    00167     return specFile;
    00168 }
    00169
    00172 static int buildForTarget(rpmts ts, const char * arg, BTA_t ba)
    00173 {
    00174     const char * passPhrase = ba->passPhrase;
    00175     const char * cookie = ba->cookie;
    00176     int buildAmount = ba->buildAmount;
    00177     char * buildRootURL = NULL;
    00178     char * specFile = NULL;
    00179     rpmSpec spec = NULL;
    00180     int rc = 1; /* assume failure */
    00181
    00182 #ifndef DYING
    00183     rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
    00184 #endif
    00185
    00186     if (ba->buildRootOverride)
    00187         buildRootURL = rpmGenPath(NULL, ba->buildRootOverride, NULL);
    00188
    00189     if (ba->buildMode == 't') {
    00190         char *srcdir = NULL, *dir;
    00191
    00192         specFile = getTarSpec(arg);
    00193         if (!specFile)
    00194             goto exit;
    00195
    00196         /* Make the directory of the tarball %_sourcedir for this run */
    00197         /* dirname() may modify contents so extra hoops needed. */
    00198         if (*arg != '/') {
    00199             dir = rpmGetCwd();
    00200             rstrscat(&dir, "/", arg, NULL);
    00201         } else {
    00202             dir = xstrdup(arg);
    00203         }
    00204         srcdir = dirname(dir);
    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     /* Be sure all required directories exist, attempt to create them if not */
    00258     {
    00259         char *_topdir = rpmGenPath(rpmtsRootDir(ts), "%{_topdir}", ""),
    00260              *_builddir = rpmGenPath(rpmtsRootDir(ts), "%{_builddir}", ""),
    00261              *_buildrootdir = rpmGenPath(rpmtsRootDir(ts), "%{_buildrootdir}", ""),
    00262              *_sourcedir = rpmGenPath(rpmtsRootDir(ts), "%{_sourcedir}", ""),
    00263              *_rpmdir = rpmGenPath(rpmtsRootDir(ts), "%{_rpmdir}", ""),
    00264              *_specdir = rpmGenPath(rpmtsRootDir(ts), "%{_specdir}", ""),
    00265              *_srcrpmdir = rpmGenPath(rpmtsRootDir(ts), "%{_srcrpmdir}", "");
    00266
    00267         if ( rpmMkdirPath(_topdir, "_topdir") ||
    00268              rpmMkdirPath(_builddir, "_builddir") ||
    00269              rpmMkdirPath(_buildrootdir, "_buildrootdir") ||
    00270              rpmMkdirPath(_sourcedir, "_sourcedir") ||
    00271              rpmMkdirPath(_rpmdir, "_rpmdir") ||
    00272              rpmMkdirPath(_specdir, "_specdir") ||
    00273              rpmMkdirPath(_srcrpmdir, "_srcrpmdir")
    00274         ) {
    00275             goto exit;
    00276         }
    00277     }
    00278
    00279     if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
    00280         goto exit;
    00281     }
    00282
    00283     if (ba->buildMode == 't')
    00284         (void) unlink(specFile);
    00285     rc = 0;
    00286
    00287 exit:
    00288     free(specFile);
    00289     freeSpec(spec);
    00290     free(buildRootURL);
    00291     return rc;
    00292 }
    00293
    00294 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile)
    00295 {
    00296     char *t, *te;
    00297     int rc = 0;
    00298     char * targets = ba->targets;
    00299 #define buildCleanMask  (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
    00300     int cleanFlags = ba->buildAmount & buildCleanMask;
    00301     rpmVSFlags vsflags, ovsflags;
    00302
    00303     vsflags = rpmExpandNumeric("%{_vsflags_build}");
    00304     if (ba->qva_flags & VERIFY_DIGEST)
    00305         vsflags |= _RPMVSF_NODIGESTS;
    00306     if (ba->qva_flags & VERIFY_SIGNATURE)
    00307         vsflags |= _RPMVSF_NOSIGNATURES;
    00308     if (ba->qva_flags & VERIFY_HDRCHK)
    00309         vsflags |= RPMVSF_NOHDRCHK;
    00310     ovsflags = rpmtsSetVSFlags(ts, vsflags);
    00311
    00312     if (targets == NULL) {
    00313         rc =  buildForTarget(ts, arg, ba);
    00314         goto exit;
    00315     }
    00316
    00317     /* parse up the build operators */
    00318
    00319     printf(_("Building target platforms: %s\n"), targets);
    00320
    00321     ba->buildAmount &= ~buildCleanMask;
    00322     for (t = targets; *t != '\0'; t = te) {
    00323         char *target;
    00324         if ((te = strchr(t, ',')) == NULL)
    00325             te = t + strlen(t);
    00326         target = xmalloc(te-t+1);
    00327         strncpy(target, t, (te-t));
    00328         target[te-t] = '\0';
    00329         if (*te != '\0')
    00330             te++;
    00331         else    /* XXX Perform clean-up after last target build. */
    00332             ba->buildAmount |= cleanFlags;
    00333
    00334         printf(_("Building for target %s\n"), target);
    00335
    00336         /* Read in configuration for target. */
    00337         rpmFreeMacros(NULL);
    00338         rpmFreeRpmrc();
    00339         (void) rpmReadConfigFiles(rcfile, target);
    00340         free(target);
    00341         rc = buildForTarget(ts, arg, ba);
    00342         if (rc)
    00343             break;
    00344     }
    00345
    00346 exit:
    00347     vsflags = rpmtsSetVSFlags(ts, ovsflags);
    00348     /* Restore original configuration. */
    00349     rpmFreeMacros(NULL);
    00350     rpmFreeRpmrc();
    00351     (void) rpmReadConfigFiles(rcfile, NULL);
    00352
    00353     return rc;
    00354 }