• 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 }

Generated on Fri Dec 3 2010 20:53:09 for rpm by  doxygen 1.7.2