rpm 5.2.1

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

- File List
- Globals

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, const char * arg, 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     size_t nb = strlen(arg) + BUFSIZ;
    00115     char * buf = alloca(nb);
    00116     Spec spec = NULL;
    00117     int verify = ((ba->buildAmount & RPMBUILD_TRACK) ? 0 : 1);
    00118     int xx;
    00119     int rc;
    00120
    00121     if (ba->buildMode == 't') {
    00122         static const char * sfpats[] = { "Specfile", "\\*.spec", NULL };
    00123         static const char _specfn[] = "%{mkstemp:%{_specdir}/rpm-spec.XXXXXX}";
    00124         char * tmpSpecFile = (char *) rpmGetPath(_specfn, NULL);
    00125         FILE *fp;
    00126         int bingo = 0;
    00127         int i;
    00128
    00129         for (i = 0; sfpats[i]; i++) {
    00130             se = rpmExpand("%{uncompress: %{u2p:", arg, "}}",
    00131                 " | %{__tar} -xOvf - %{?__tar_wildcards} ", sfpats[i],
    00132                 " 2>&1 > '", tmpSpecFile, "'", NULL);
    00133             fp = popen(se, "r");
    00134             se = _free(se);
    00135             if (fp== NULL)
    00136                 continue;
    00137             s = fgets(buf, nb - 1, fp);
    00138             xx = pclose(fp);
    00139             if (!s || !*s || strstr(s, ": Not found in archive"))
    00140                 continue;
    00141             bingo = 1;
    00142             break;
    00143         }
    00144         if (!bingo) {
    00145             rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg);
    00146             xx = Unlink(tmpSpecFile);
    00147             tmpSpecFile = _free(tmpSpecFile);
    00148             return 1;
    00149         }
    00150
    00151         s = se = basename(buf);
    00152         se += strlen(se);
    00153         while (--se > s && strchr("\r\n", *se) != NULL)
    00154             *se = '\0';
    00155         specURL = rpmGetPath("%{_specdir}/", s, NULL);
    00156         specut = urlPath(specURL, &specFile);
    00157         xx = Rename(tmpSpecFile, specFile);
    00158         if (xx) {
    00159             rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"),
    00160                         tmpSpecFile, s);
    00161             (void) Unlink(tmpSpecFile);
    00162         }
    00163         tmpSpecFile = _free(tmpSpecFile);
    00164         if (xx)
    00165             return 1;
    00166
    00167         se = buf; *se = '\0';
    00168         se = stpcpy(se, "_sourcedir ");
    00169         (void) urlPath(arg, &s);
    00170         if (*s != '/') {
    00171             if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL)
    00172                 se += strlen(se);
    00173             else
    00174                 se = stpcpy(se, ".");
    00175         } else
    00176             se = stpcpy(se, dirname(strcpy(se, s)));
    00177         while (se > buf && se[-1] == '/')
    00178             *se-- = '0';
    00179         rpmCleanPath(buf + sizeof("_sourcedir ") - 1);
    00180         rpmDefineMacro(NULL, buf, RMIL_TARBALL);
    00181     } else {
    00182         specut = urlPath(arg, &s);
    00183         se = buf; *se = '\0';
    00184         if (*s != '/') {
    00185             if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL)
    00186                 se += strlen(se);
    00187             else
    00188                 se = stpcpy(se, ".");
    00189             *se++ = '/';
    00190             se += strlen(strcpy(se,strcpy(se, s)));
    00191         } else
    00192             se = stpcpy(se, s);
    00193         specURL = rpmGetPath(buf, NULL);
    00194         specut = urlPath(specURL, &specFile);
    00195     }
    00196
    00197     if (specut != URL_IS_DASH) {
    00198         struct stat sb;
    00199         if (Stat(specURL, &sb) < 0) {
    00200             rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specURL);
    00201             rc = 1;
    00202             goto exit;
    00203         }
    00204         if (! S_ISREG(sb.st_mode)) {
    00205             rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"),
    00206                 specURL);
    00207             rc = 1;
    00208             goto exit;
    00209         }
    00210
    00211         /* Try to verify that the file is actually a specfile */
    00212         if (!isSpecFile(specURL)) {
    00213             rpmlog(RPMLOG_ERR,
    00214                 _("File %s does not appear to be a specfile.\n"), specURL);
    00215             rc = 1;
    00216             goto exit;
    00217         }
    00218     }
    00219
    00220     /* Parse the spec file */
    00221 #define _anyarch(_f)    \
    00222 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
    00223     if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase,
    00224                 cookie, _anyarch(buildAmount), 0, verify))
    00225     {
    00226         rc = 1;
    00227         goto exit;
    00228     }
    00229 #undef  _anyarch
    00230     if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
    00231         rc = 1;
    00232         goto exit;
    00233     }
    00234
    00235     /* Assemble source header from parsed components */
    00236     xx = initSourceHeader(spec, NULL);
    00237
    00238     /* Check build prerequisites */
    00239     if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
    00240         rc = 1;
    00241         goto exit;
    00242     }
    00243
    00244     if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
    00245         rc = 1;
    00246         goto exit;
    00247     }
    00248
    00249     if (ba->buildMode == 't')
    00250         (void) Unlink(specURL);
    00251     rc = 0;
    00252
    00253 exit:
    00254     spec = freeSpec(spec);
    00255     specURL = _free(specURL);
    00256     return rc;
    00257 }
    00258 /*@=boundswrite@*/
    00259
    00260 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile)
    00261 {
    00262     const char *t, *te;
    00263     int rc = 0;
    00264     const char * targets = rpmcliTargets;
    00265     char *target;
    00266 #define buildCleanMask  (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
    00267     int cleanFlags = ba->buildAmount & buildCleanMask;
    00268     rpmVSFlags vsflags, ovsflags;
    00269     int nbuilds = 0;
    00270
    00271     vsflags = rpmExpandNumeric("%{_vsflags_build}");
    00272     if (ba->qva_flags & VERIFY_DIGEST)
    00273         vsflags |= _RPMVSF_NODIGESTS;
    00274     if (ba->qva_flags & VERIFY_SIGNATURE)
    00275         vsflags |= _RPMVSF_NOSIGNATURES;
    00276     if (ba->qva_flags & VERIFY_HDRCHK)
    00277         vsflags |= RPMVSF_NOHDRCHK;
    00278     ovsflags = rpmtsSetVSFlags(ts, vsflags);
    00279
    00280     if (targets == NULL) {
    00281         rc =  buildForTarget(ts, arg, ba);
    00282         nbuilds++;
    00283         goto exit;
    00284     }
    00285
    00286     /* parse up the build operators */
    00287
    00288     printf(_("Building target platforms: %s\n"), targets);
    00289
    00290     ba->buildAmount &= ~buildCleanMask;
    00291     for (t = targets; *t != '\0'; t = te) {
    00292         /* Parse out next target platform. */
    00293         if ((te = strchr(t, ',')) == NULL)
    00294             te = t + strlen(t);
    00295         target = alloca(te-t+1);
    00296         strncpy(target, t, (te-t));
    00297         target[te-t] = '\0';
    00298         if (*te != '\0')
    00299             te++;
    00300         else    /* XXX Perform clean-up after last target build. */
    00301             ba->buildAmount |= cleanFlags;
    00302
    00303         rpmlog(RPMLOG_DEBUG, _("    target platform: %s\n"), target);
    00304
    00305         /* Read in configuration for target. */
    00306         if (t != targets) {
    00307             rpmFreeMacros(NULL);
    00308             rpmFreeRpmrc();
    00309             (void) rpmReadConfigFiles(rcfile, target);
    00310         }
    00311         rc = buildForTarget(ts, arg, ba);
    00312         nbuilds++;
    00313         if (rc)
    00314             break;
    00315     }
    00316
    00317 exit:
    00318     /* Restore original configuration. */
    00319     if (nbuilds > 1) {
    00320         t = targets;
    00321         if ((te = strchr(t, ',')) == NULL)
    00322             te = t + strlen(t);
    00323         target = alloca(te-t+1);
    00324         strncpy(target, t, (te-t));
    00325         target[te-t] = '\0';
    00326         if (*te != '\0')
    00327             te++;
    00328         rpmFreeMacros(NULL);
    00329         rpmFreeRpmrc();
    00330         (void) rpmReadConfigFiles(rcfile, target);
    00331     }
    00332     vsflags = rpmtsSetVSFlags(ts, ovsflags);
    00333
    00334     return rc;
    00335 }