rpm 5.3.7

build.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <rpmio.h>
00008 #include <rpmiotypes.h>
00009 #include <rpmcb.h>
00010 #include <rpmurl.h>
00011 
00012 #include <rpmtypes.h>
00013 #include <rpmtag.h>
00014 
00015 #include <rpmbuild.h>
00016 
00017 #include "rpmps.h"
00018 #include "rpmte.h"
00019 #include "rpmts.h"
00020 
00021 #include "build.h"
00022 
00023 #include <rpmcli.h>
00024 
00025 #include "debug.h"
00026 
00027 /*@access rpmts @*/     /* XXX compared with NULL @*/
00028 /*@access rpmdb @*/             /* XXX compared with NULL @*/
00029 /*@access FD_t @*/              /* XXX compared with NULL @*/
00030 
00033 static int checkSpec(rpmts ts, Header h)
00034         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00035         /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/
00036 {
00037     int rc;
00038 
00039     if (!headerIsEntry(h, RPMTAG_REQUIRENAME)
00040      && !headerIsEntry(h, RPMTAG_CONFLICTNAME))
00041         return 0;
00042 
00043     rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
00044 
00045     rc = rpmcliInstallProblems(ts, _("Failed build dependencies"), rpmtsCheck(ts));
00046 
00047     /* XXX nuke the added package. */
00048     rpmtsClean(ts);
00049 
00050     return rc;
00051 }
00052 
00053 /*
00054  * Kurwa, durni ameryka?ce sobe zawsze my?l?, ?e ca?y ?wiat mówi po
00055  * angielsku...
00056  */
00057 /* XXX this is still a dumb test but at least it's i18n aware */
00060 static int isSpecFile(const char * specfile)
00061         /*@globals h_errno, fileSystem, internalState @*/
00062         /*@modifies fileSystem, internalState @*/
00063 {
00064     char buf[256];
00065     const char * s;
00066     FD_t fd;
00067     int count;
00068     int checking;
00069 
00070     fd = Fopen(specfile, "r");
00071     if (fd == NULL || Ferror(fd)) {
00072         rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"),
00073                 specfile, Fstrerror(fd));
00074         return 0;
00075     }
00076     count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
00077     (void) Fclose(fd);
00078 
00079     checking = 1;
00080     for (s = buf; count--; s++) {
00081         switch (*s) {
00082         case '\r':
00083         case '\n':
00084             checking = 1;
00085             /*@switchbreak@*/ break;
00086         case ':':
00087             checking = 0;
00088             /*@switchbreak@*/ break;
00089 /*@-boundsread@*/
00090         default:
00091             if (checking && !(isprint(*s) || isspace(*s))) return 0;
00092             /*@switchbreak@*/ break;
00093 /*@=boundsread@*/
00094         }
00095     }
00096     return 1;
00097 }
00098 
00101 /*@-boundswrite@*/
00102 static int buildForTarget(rpmts ts, BTA_t ba)
00103         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00104         /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
00105 {
00106     const char * passPhrase = ba->passPhrase;
00107     const char * cookie = ba->cookie;
00108     int buildAmount = ba->buildAmount;
00109     const char * specFile = NULL;
00110     const char * specURL = NULL;
00111     int specut;
00112     const char * s;
00113     char * se;
00114     const char * arg = ba->specFile;
00115     size_t nb = strlen(arg) + BUFSIZ;
00116     char * buf = alloca(nb);
00117     Spec spec = NULL;
00118     int verify = ((ba->buildAmount & RPMBUILD_TRACK) ? 0 : 1);
00119     int xx;
00120     int rc;
00121 
00122     if (ba->buildMode == 't') {
00123         static const char * sfpats[] = { "Specfile", "\\*.spec", NULL };
00124         static const char _specfn[] = "%{mkstemp:%{_specdir}/rpm-spec.XXXXXX}";
00125         char * tmpSpecFile = (char *) rpmGetPath(_specfn, NULL);
00126         FILE *fp;
00127         int bingo = 0;
00128         int i;
00129 
00130         for (i = 0; sfpats[i]; i++) {
00131             se = rpmExpand("%{uncompress: %{u2p:", arg, "}}",
00132                 " | %{__tar} -xOvf - %{?__tar_wildcards} ", sfpats[i],
00133                 " 2>&1 > '", tmpSpecFile, "'", NULL);
00134             fp = popen(se, "r");
00135             se = _free(se);
00136             if (fp== NULL)
00137                 continue;
00138             s = fgets(buf, nb - 1, fp);
00139             xx = pclose(fp);
00140             if (!s || !*s || strstr(s, ": Not found in archive"))
00141                 continue;
00142             bingo = 1;
00143             break;
00144         }
00145         if (!bingo) {
00146             rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg);
00147             xx = Unlink(tmpSpecFile);
00148             tmpSpecFile = _free(tmpSpecFile);
00149             return 1;
00150         }
00151 
00152         s = se = basename(buf);
00153         se += strlen(se);
00154         while (--se > s && strchr("\r\n", *se) != NULL)
00155             *se = '\0';
00156         specURL = rpmGetPath("%{_specdir}/", s, NULL);
00157         specut = urlPath(specURL, &specFile);
00158         xx = Rename(tmpSpecFile, specFile);
00159         if (xx) {
00160             rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"),
00161                         tmpSpecFile, s);
00162             (void) Unlink(tmpSpecFile);
00163         }
00164         tmpSpecFile = _free(tmpSpecFile);
00165         if (xx)
00166             return 1;
00167 
00168         se = buf; *se = '\0';
00169         se = stpcpy(se, "_sourcedir ");
00170         (void) urlPath(arg, &s);
00171         if (*s != '/') {
00172             if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL)
00173                 se += strlen(se);
00174             else
00175                 se = stpcpy(se, ".");
00176         } else
00177             se = stpcpy(se, dirname(strcpy(se, s)));
00178         while (se > buf && se[-1] == '/')
00179             *se-- = '0';
00180         rpmCleanPath(buf + sizeof("_sourcedir ") - 1);
00181         rpmDefineMacro(NULL, buf, RMIL_TARBALL);
00182     } else {
00183         specut = urlPath(arg, &s);
00184         se = buf; *se = '\0';
00185         if (*s != '/') {
00186             if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL)
00187                 se += strlen(se);
00188             else
00189                 se = stpcpy(se, ".");
00190             *se++ = '/';
00191             se += strlen(strcpy(se,strcpy(se, s)));
00192         } else
00193             se = stpcpy(se, s);
00194         specURL = rpmGetPath(buf, NULL);
00195         specut = urlPath(specURL, &specFile);
00196     }
00197 
00198     if (specut != URL_IS_DASH) {
00199         struct stat sb;
00200         if (Stat(specURL, &sb) < 0) {
00201             rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specURL);
00202             rc = 1;
00203             goto exit;
00204         }
00205         if (! S_ISREG(sb.st_mode)) {
00206             rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"),
00207                 specURL);
00208             rc = 1;
00209             goto exit;
00210         }
00211 
00212         /* Try to verify that the file is actually a specfile */
00213         if (!isSpecFile(specURL)) {
00214             rpmlog(RPMLOG_ERR,
00215                 _("File %s does not appear to be a specfile.\n"), specURL);
00216             rc = 1;
00217             goto exit;
00218         }
00219     }
00220     
00221     /* Parse the spec file */
00222 #define _anyarch(_f)    \
00223 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
00224     if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase,
00225                 cookie, _anyarch(buildAmount), 0, verify))
00226     {
00227         rc = 1;
00228         goto exit;
00229     }
00230 #undef  _anyarch
00231     if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
00232         rc = 1;
00233         goto exit;
00234     }
00235 
00236     /* Assemble source header from parsed components */
00237     xx = initSourceHeader(spec, NULL);
00238 
00239     /* Check build prerequisites */
00240     if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
00241         rc = 1;
00242         goto exit;
00243     }
00244 
00245     if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
00246         rc = 1;
00247         goto exit;
00248     }
00249     
00250     if (ba->buildMode == 't')
00251         (void) Unlink(specURL);
00252     rc = 0;
00253 
00254 exit:
00255     spec = freeSpec(spec);
00256     specURL = _free(specURL);
00257     return rc;
00258 }
00259 /*@=boundswrite@*/
00260 
00261 int build(rpmts ts, BTA_t ba, const char * rcfile)
00262 {
00263     const char *t, *te;
00264     int rc = 0;
00265     const char * targets = rpmcliTargets;
00266     char *target;
00267 #define buildCleanMask  (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
00268     int cleanFlags = ba->buildAmount & buildCleanMask;
00269     rpmVSFlags vsflags, ovsflags;
00270     int nbuilds = 0;
00271 
00272     vsflags = rpmExpandNumeric("%{_vsflags_build}");
00273     if (ba->qva_flags & VERIFY_DIGEST)
00274         vsflags |= _RPMVSF_NODIGESTS;
00275     if (ba->qva_flags & VERIFY_SIGNATURE)
00276         vsflags |= _RPMVSF_NOSIGNATURES;
00277     if (ba->qva_flags & VERIFY_HDRCHK)
00278         vsflags |= RPMVSF_NOHDRCHK;
00279     ovsflags = rpmtsSetVSFlags(ts, vsflags);
00280 
00281     if (targets == NULL) {
00282         rc =  buildForTarget(ts, ba);
00283         nbuilds++;
00284         goto exit;
00285     }
00286 
00287     /* parse up the build operators */
00288 
00289     printf(_("Building target platforms: %s\n"), targets);
00290 
00291     ba->buildAmount &= ~buildCleanMask;
00292     for (t = targets; *t != '\0'; t = te) {
00293         /* Parse out next target platform. */ 
00294         if ((te = strchr(t, ',')) == NULL)
00295             te = t + strlen(t);
00296         target = alloca(te-t+1);
00297         strncpy(target, t, (te-t));
00298         target[te-t] = '\0';
00299         if (*te != '\0')
00300             te++;
00301         else    /* XXX Perform clean-up after last target build. */
00302             ba->buildAmount |= cleanFlags;
00303 
00304         rpmlog(RPMLOG_DEBUG, _("    target platform: %s\n"), target);
00305 
00306         /* Read in configuration for target. */
00307         if (t != targets) {
00308             rpmFreeMacros(NULL);
00309             rpmFreeRpmrc();
00310             (void) rpmReadConfigFiles(rcfile, target);
00311         }
00312         rc = buildForTarget(ts, ba);
00313         nbuilds++;
00314         if (rc)
00315             break;
00316     }
00317 
00318 exit:
00319     /* Restore original configuration. */
00320     if (nbuilds > 1) {
00321         t = targets;
00322         if ((te = strchr(t, ',')) == NULL)
00323             te = t + strlen(t);
00324         target = alloca(te-t+1);
00325         strncpy(target, t, (te-t));
00326         target[te-t] = '\0';
00327         if (*te != '\0')
00328             te++;
00329         rpmFreeMacros(NULL);
00330         rpmFreeRpmrc();
00331         (void) rpmReadConfigFiles(rcfile, target);
00332     }
00333     vsflags = rpmtsSetVSFlags(ts, ovsflags);
00334 
00335     return rc;
00336 }