build.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <rpmcli.h>
00008 #include <rpmbuild.h>
00009 
00010 #include "rpmps.h"
00011 #include "rpmte.h"
00012 #include "rpmts.h"
00013 
00014 #include "build.h"
00015 #include "debug.h"
00016 
00017 /*@access rpmts @*/     /* XXX compared with NULL @*/
00018 /*@access rpmdb @*/             /* XXX compared with NULL @*/
00019 /*@access FD_t @*/              /* XXX compared with NULL @*/
00020 
00023 static int checkSpec(rpmts ts, Header h)
00024         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00025         /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/
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         rpmMessage(RPMMESS_ERROR, _("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 
00052 /*
00053  * Kurwa, durni ameryka?ce sobe zawsze my?l?, ?e ca?y ?wiat mówi po
00054  * angielsku...
00055  */
00056 /* XXX this is still a dumb test but at least it's i18n aware */
00059 static int isSpecFile(const char * specfile)
00060         /*@globals h_errno, fileSystem, internalState @*/
00061         /*@modifies fileSystem, internalState @*/
00062 {
00063     char buf[256];
00064     const char * s;
00065     FD_t fd;
00066     int count;
00067     int checking;
00068 
00069     fd = Fopen(specfile, "r");
00070     if (fd == NULL || Ferror(fd)) {
00071         rpmError(RPMERR_OPEN, _("Unable to open spec file %s: %s\n"),
00072                 specfile, Fstrerror(fd));
00073         return 0;
00074     }
00075     count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
00076     (void) Fclose(fd);
00077 
00078     checking = 1;
00079     for (s = buf; count--; s++) {
00080         switch (*s) {
00081         case '\r':
00082         case '\n':
00083             checking = 1;
00084             /*@switchbreak@*/ break;
00085         case ':':
00086             checking = 0;
00087             /*@switchbreak@*/ break;
00088 /*@-boundsread@*/
00089         default:
00090             if (checking && !(isprint(*s) || isspace(*s))) return 0;
00091             /*@switchbreak@*/ break;
00092 /*@=boundsread@*/
00093         }
00094     }
00095     return 1;
00096 }
00097 
00100 /*@-boundswrite@*/
00101 static int buildForTarget(rpmts ts, const char * arg, BTA_t ba)
00102         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00103         /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
00104 {
00105     const char * passPhrase = ba->passPhrase;
00106     const char * cookie = ba->cookie;
00107     int buildAmount = ba->buildAmount;
00108     const char * specFile;
00109     const char * specURL;
00110     int specut;
00111     char buf[BUFSIZ];
00112     Spec spec = NULL;
00113     int verify = 1;
00114     int xx;
00115     int rc;
00116 
00117 #ifndef DYING
00118     rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
00119 #endif
00120 
00121     /*@-compmempass@*/ /* FIX: static zcmds heartburn */
00122     if (ba->buildMode == 't') {
00123         FILE *fp;
00124         const char * specDir;
00125         char * tmpSpecFile;
00126         char * cmd, * s;
00127         rpmCompressedMagic res = COMPRESSED_OTHER;
00128         /*@observer@*/ static const char *zcmds[] =
00129                 { "cat", "gunzip", "bunzip2", "cat" };
00130 
00131         specDir = rpmGetPath("%{_specdir}", NULL);
00132 
00133         tmpSpecFile = (char *) rpmGetPath("%{_specdir}/", "rpm-spec.XXXXXX", NULL);
00134 #if defined(HAVE_MKSTEMP)
00135         (void) close(mkstemp(tmpSpecFile));
00136 #else
00137         (void) mktemp(tmpSpecFile);
00138 #endif
00139 
00140         (void) isCompressed(arg, &res);
00141 
00142         cmd = alloca(strlen(arg) + 50 + strlen(tmpSpecFile));
00143         sprintf(cmd, "%s < %s | tar xOvf - Specfile 2>&1 > %s",
00144                         zcmds[res & 0x3], arg, tmpSpecFile);
00145         if (!(fp = popen(cmd, "r"))) {
00146             rpmError(RPMERR_POPEN, _("Failed to open tar pipe: %m\n"));
00147             specDir = _free(specDir);
00148             tmpSpecFile = _free(tmpSpecFile);
00149             return 1;
00150         }
00151         if ((!fgets(buf, sizeof(buf) - 1, fp)) || !strchr(buf, '/')) {
00152             /* Try again */
00153             (void) pclose(fp);
00154 
00155             sprintf(cmd, "%s < %s | tar xOvf - \\*.spec 2>&1 > %s",
00156                     zcmds[res & 0x3], arg, tmpSpecFile);
00157             if (!(fp = popen(cmd, "r"))) {
00158                 rpmError(RPMERR_POPEN, _("Failed to open tar pipe: %m\n"));
00159                 specDir = _free(specDir);
00160                 tmpSpecFile = _free(tmpSpecFile);
00161                 return 1;
00162             }
00163             if (!fgets(buf, sizeof(buf) - 1, fp)) {
00164                 /* Give up */
00165                 rpmError(RPMERR_READ, _("Failed to read spec file from %s\n"),
00166                         arg);
00167                 (void) unlink(tmpSpecFile);
00168                 specDir = _free(specDir);
00169                 tmpSpecFile = _free(tmpSpecFile);
00170                 return 1;
00171             }
00172         }
00173         (void) pclose(fp);
00174 
00175         cmd = s = buf;
00176         while (*cmd != '\0') {
00177             if (*cmd == '/') s = cmd + 1;
00178             cmd++;
00179         }
00180 
00181         cmd = s;
00182 
00183         /* remove trailing \n */
00184         s = cmd + strlen(cmd) - 1;
00185         *s = '\0';
00186 
00187         specURL = s = alloca(strlen(specDir) + strlen(cmd) + 5);
00188         sprintf(s, "%s/%s", specDir, cmd);
00189         res = rename(tmpSpecFile, s);
00190         specDir = _free(specDir);
00191         
00192         if (res) {
00193             rpmError(RPMERR_RENAME, _("Failed to rename %s to %s: %m\n"),
00194                         tmpSpecFile, s);
00195             (void) unlink(tmpSpecFile);
00196             tmpSpecFile = _free(tmpSpecFile);
00197             return 1;
00198         }
00199         tmpSpecFile = _free(tmpSpecFile);
00200 
00201         /* Make the directory which contains the tarball the source 
00202            directory for this run */
00203 
00204         if (*arg != '/') {
00205             if (getcwd(buf, BUFSIZ) == NULL) strcpy(buf, ".");
00206             strcat(buf, "/");
00207             strcat(buf, arg);
00208         } else 
00209             strcpy(buf, arg);
00210 
00211         cmd = buf + strlen(buf) - 1;
00212         while (*cmd != '/') cmd--;
00213         *cmd = '\0';
00214 
00215         addMacro(NULL, "_sourcedir", NULL, buf, RMIL_TARBALL);
00216     } else {
00217         specURL = arg;
00218     }
00219     /*@=compmempass@*/
00220 
00221     specut = urlPath(specURL, &specFile);
00222     if (*specFile != '/') {
00223         char *s = alloca(BUFSIZ);
00224         if (getcwd(s, BUFSIZ) == NULL) strcpy(s, ".");
00225         strcat(s, "/");
00226         strcat(s, arg);
00227         specURL = s;
00228     }
00229 
00230     if (specut != URL_IS_DASH) {
00231         struct stat st;
00232         if (Stat(specURL, &st) < 0) {
00233             rpmError(RPMERR_STAT, _("failed to stat %s: %m\n"), specURL);
00234             rc = 1;
00235             goto exit;
00236         }
00237         if (! S_ISREG(st.st_mode)) {
00238             rpmError(RPMERR_NOTREG, _("File %s is not a regular file.\n"),
00239                 specURL);
00240             rc = 1;
00241             goto exit;
00242         }
00243 
00244         /* Try to verify that the file is actually a specfile */
00245         if (!isSpecFile(specURL)) {
00246             rpmError(RPMERR_BADSPEC,
00247                 _("File %s does not appear to be a specfile.\n"), specURL);
00248             rc = 1;
00249             goto exit;
00250         }
00251     }
00252     
00253     /* Parse the spec file */
00254 #define _anyarch(_f)    \
00255 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
00256     if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase,
00257                 cookie, _anyarch(buildAmount), ba->force, verify))
00258     {
00259         rc = 1;
00260         goto exit;
00261     }
00262 #undef  _anyarch
00263     if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
00264         rc = 1;
00265         goto exit;
00266     }
00267 
00268     /* Assemble source header from parsed components */
00269     xx = initSourceHeader(spec, NULL);
00270 
00271     /* Check build prerequisites */
00272     if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
00273         rc = 1;
00274         goto exit;
00275     }
00276 
00277     if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
00278         rc = 1;
00279         goto exit;
00280     }
00281     
00282     if (ba->buildMode == 't')
00283         (void) Unlink(specURL);
00284     rc = 0;
00285 
00286 exit:
00287     spec = freeSpec(spec);
00288     return rc;
00289 }
00290 /*@=boundswrite@*/
00291 
00292 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile)
00293 {
00294     const char *t, *te;
00295     int rc = 0;
00296     const char * targets = rpmcliTargets;
00297     char *target;
00298 #define buildCleanMask  (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
00299     int cleanFlags = ba->buildAmount & buildCleanMask;
00300     rpmVSFlags vsflags, ovsflags;
00301     int nbuilds = 0;
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         nbuilds++;
00315         goto exit;
00316     }
00317 
00318     /* parse up the build operators */
00319 
00320     printf(_("Building target platforms: %s\n"), targets);
00321 
00322     ba->buildAmount &= ~buildCleanMask;
00323     for (t = targets; *t != '\0'; t = te) {
00324         /* Parse out next target platform. */ 
00325         if ((te = strchr(t, ',')) == NULL)
00326             te = t + strlen(t);
00327         target = alloca(te-t+1);
00328         strncpy(target, t, (te-t));
00329         target[te-t] = '\0';
00330         if (*te != '\0')
00331             te++;
00332         else    /* XXX Perform clean-up after last target build. */
00333             ba->buildAmount |= cleanFlags;
00334 
00335         rpmMessage(RPMMESS_DEBUG, _("    target platform: %s\n"), target);
00336 
00337         /* Read in configuration for target. */
00338         if (t != targets) {
00339             rpmFreeMacros(NULL);
00340             rpmFreeRpmrc();
00341             (void) rpmReadConfigFiles(rcfile, target);
00342         }
00343         rc = buildForTarget(ts, arg, ba);
00344         nbuilds++;
00345         if (rc)
00346             break;
00347     }
00348 
00349 exit:
00350     /* Restore original configuration. */
00351     if (nbuilds > 1) {
00352         t = targets;
00353         if ((te = strchr(t, ',')) == NULL)
00354             te = t + strlen(t);
00355         target = alloca(te-t+1);
00356         strncpy(target, t, (te-t));
00357         target[te-t] = '\0';
00358         if (*te != '\0')
00359             te++;
00360         rpmFreeMacros(NULL);
00361         rpmFreeRpmrc();
00362         (void) rpmReadConfigFiles(rcfile, target);
00363     }
00364     vsflags = rpmtsSetVSFlags(ts, ovsflags);
00365 
00366     return rc;
00367 }

Generated on Fri May 25 21:18:11 2007 for rpm by  doxygen 1.5.2