Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

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 "build.h"
00011 #include "debug.h"
00012 
00013 /*@access rpmTransactionSet @*/ /* XXX compared with NULL @*/
00014 /*@access rpmdb @*/             /* XXX compared with NULL @*/
00015 /*@access FD_t @*/              /* XXX compared with NULL @*/
00016 
00019 static int checkSpec(Header h)
00020         /*@globals rpmGlobalMacroContext,
00021                 fileSystem, internalState @*/
00022         /*@modifies h, rpmGlobalMacroContext,
00023                 fileSystem, internalState @*/
00024 {
00025     const char * rootdir = NULL;
00026     rpmdb db = NULL;
00027     int mode = O_RDONLY;
00028     rpmTransactionSet ts;
00029     rpmDependencyConflict conflicts;
00030     int numConflicts;
00031     int rc;
00032 
00033     if (!headerIsEntry(h, RPMTAG_REQUIREFLAGS))
00034         return 0;
00035 
00036     if (rpmdbOpen(rootdir, &db, mode, 0644)) {
00037         const char * dn;
00038         dn = rpmGetPath( (rootdir ? rootdir : ""), "%{_dbpath}", NULL);
00039         rpmError(RPMERR_OPEN, _("cannot open rpm database in %s\n"), dn);
00040         dn = _free(dn);
00041         exit(EXIT_FAILURE);
00042     }
00043     ts = rpmtransCreateSet(db, rootdir);
00044 
00045     rc = rpmtransAddPackage(ts, h, NULL, NULL, 0, NULL);
00046 
00047     rc = rpmdepCheck(ts, &conflicts, &numConflicts);
00048     if (rc == 0 && conflicts) {
00049         rpmMessage(RPMMESS_ERROR, _("failed build dependencies:\n"));
00050         printDepProblems(stderr, conflicts, numConflicts);
00051         conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
00052         rc = 1;
00053     }
00054 
00055     ts = rpmtransFree(ts);
00056     if (db != NULL)
00057         (void) rpmdbClose(db);
00058 
00059     return rc;
00060 }
00061 
00062 /*
00063  * Kurwa, durni ameryka?ce sobe zawsze my?l?, ?e ca?y ?wiat mówi po
00064  * angielsku...
00065  */
00066 /* XXX this is still a dumb test but at least it's i18n aware */
00069 static int isSpecFile(const char * specfile)
00070         /*@globals fileSystem @*/
00071         /*@modifies fileSystem @*/
00072 {
00073     char buf[256];
00074     const char * s;
00075     FD_t fd;
00076     int count;
00077     int checking;
00078 
00079     fd = Fopen(specfile, "r.ufdio");
00080     if (fd == NULL || Ferror(fd)) {
00081         rpmError(RPMERR_OPEN, _("Unable to open spec file %s: %s\n"),
00082                 specfile, Fstrerror(fd));
00083         return 0;
00084     }
00085     count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
00086     (void) Fclose(fd);
00087 
00088     checking = 1;
00089     for (s = buf; count--; s++) {
00090         switch (*s) {
00091         case '\r':
00092         case '\n':
00093             checking = 1;
00094             /*@switchbreak@*/ break;
00095         case ':':
00096             checking = 0;
00097             /*@switchbreak@*/ break;
00098         default:
00099             if (checking && !(isprint(*s) || isspace(*s))) return 0;
00100             /*@switchbreak@*/ break;
00101         }
00102     }
00103     return 1;
00104 }
00105 
00108 static int buildForTarget(const char * arg, BTA_t ba,
00109                 const char * passPhrase, char * cookie)
00110         /*@globals rpmGlobalMacroContext,
00111                 fileSystem, internalState @*/
00112         /*@modifies rpmGlobalMacroContext,
00113                 fileSystem, internalState @*/
00114 {
00115     int buildAmount = ba->buildAmount;
00116     const char * buildRootURL = NULL;
00117     const char * specFile;
00118     const char * specURL;
00119     int specut;
00120     char buf[BUFSIZ];
00121     Spec spec = NULL;
00122     int rc;
00123 
00124 #ifndef DYING
00125     rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
00126 #endif
00127 
00128     /*@-branchstate@*/
00129     if (ba->buildRootOverride)
00130         buildRootURL = rpmGenPath(NULL, ba->buildRootOverride, NULL);
00131     /*@=branchstate@*/
00132 
00133     /*@-compmempass@*/ /* FIX: static zcmds heartburn */
00134     if (ba->buildMode == 't') {
00135         FILE *fp;
00136         const char * specDir;
00137         const char * tmpSpecFile;
00138         char * cmd, * s;
00139         rpmCompressedMagic res = COMPRESSED_OTHER;
00140         /*@observer@*/ static const char *zcmds[] =
00141                 { "cat", "gunzip", "bunzip2", "cat" };
00142 
00143         specDir = rpmGetPath("%{_specdir}", NULL);
00144 
00145         /* XXX Using mkstemp is difficult here. */
00146         /* XXX FWIW, default %{_specdir} is root.root 0755 */
00147         {   char tfn[64];
00148             strcpy(tfn, "rpm-spec.XXXXXX");
00149             /*@-unrecog@*/
00150             tmpSpecFile = rpmGetPath("%{_specdir}/", mktemp(tfn), NULL);
00151             /*@=unrecog@*/
00152         }
00153 
00154         (void) isCompressed(arg, &res);
00155 
00156         cmd = alloca(strlen(arg) + 50 + strlen(tmpSpecFile));
00157         sprintf(cmd, "%s < %s | tar xOvf - Specfile 2>&1 > %s",
00158                         zcmds[res & 0x3], arg, tmpSpecFile);
00159         if (!(fp = popen(cmd, "r"))) {
00160             rpmError(RPMERR_POPEN, _("Failed to open tar pipe: %m\n"));
00161             specDir = _free(specDir);
00162             tmpSpecFile = _free(tmpSpecFile);
00163             return 1;
00164         }
00165         if ((!fgets(buf, sizeof(buf) - 1, fp)) || !strchr(buf, '/')) {
00166             /* Try again */
00167             (void) pclose(fp);
00168 
00169             sprintf(cmd, "%s < %s | tar xOvf - \\*.spec 2>&1 > %s",
00170                     zcmds[res & 0x3], arg, tmpSpecFile);
00171             if (!(fp = popen(cmd, "r"))) {
00172                 rpmError(RPMERR_POPEN, _("Failed to open tar pipe: %m\n"));
00173                 specDir = _free(specDir);
00174                 tmpSpecFile = _free(tmpSpecFile);
00175                 return 1;
00176             }
00177             if (!fgets(buf, sizeof(buf) - 1, fp)) {
00178                 /* Give up */
00179                 rpmError(RPMERR_READ, _("Failed to read spec file from %s\n"),
00180                         arg);
00181                 (void) unlink(tmpSpecFile);
00182                 specDir = _free(specDir);
00183                 tmpSpecFile = _free(tmpSpecFile);
00184                 return 1;
00185             }
00186         }
00187         (void) pclose(fp);
00188 
00189         cmd = s = buf;
00190         while (*cmd != '\0') {
00191             if (*cmd == '/') s = cmd + 1;
00192             cmd++;
00193         }
00194 
00195         cmd = s;
00196 
00197         /* remove trailing \n */
00198         s = cmd + strlen(cmd) - 1;
00199         *s = '\0';
00200 
00201         specURL = s = alloca(strlen(specDir) + strlen(cmd) + 5);
00202         sprintf(s, "%s/%s", specDir, cmd);
00203         res = rename(tmpSpecFile, s);
00204         specDir = _free(specDir);
00205         
00206         if (res) {
00207             rpmError(RPMERR_RENAME, _("Failed to rename %s to %s: %m\n"),
00208                         tmpSpecFile, s);
00209             (void) unlink(tmpSpecFile);
00210             tmpSpecFile = _free(tmpSpecFile);
00211             return 1;
00212         }
00213         tmpSpecFile = _free(tmpSpecFile);
00214 
00215         /* Make the directory which contains the tarball the source 
00216            directory for this run */
00217 
00218         if (*arg != '/') {
00219             (void)getcwd(buf, BUFSIZ);
00220             strcat(buf, "/");
00221             strcat(buf, arg);
00222         } else 
00223             strcpy(buf, arg);
00224 
00225         cmd = buf + strlen(buf) - 1;
00226         while (*cmd != '/') cmd--;
00227         *cmd = '\0';
00228 
00229         addMacro(NULL, "_sourcedir", NULL, buf, RMIL_TARBALL);
00230     } else {
00231         specURL = arg;
00232     }
00233     /*@=compmempass@*/
00234 
00235     specut = urlPath(specURL, &specFile);
00236     if (*specFile != '/') {
00237         char *s = alloca(BUFSIZ);
00238         (void)getcwd(s, BUFSIZ);
00239         strcat(s, "/");
00240         strcat(s, arg);
00241         specURL = s;
00242     }
00243 
00244     if (specut != URL_IS_DASH) {
00245         struct stat st;
00246         if (Stat(specURL, &st) < 0) {
00247             rpmError(RPMERR_STAT, _("failed to stat %s: %m\n"), specURL);
00248             rc = 1;
00249             goto exit;
00250         }
00251         if (! S_ISREG(st.st_mode)) {
00252             rpmError(RPMERR_NOTREG, _("File %s is not a regular file.\n"),
00253                 specURL);
00254             rc = 1;
00255             goto exit;
00256         }
00257 
00258         /* Try to verify that the file is actually a specfile */
00259         if (!isSpecFile(specURL)) {
00260             rpmError(RPMERR_BADSPEC,
00261                 _("File %s does not appear to be a specfile.\n"), specURL);
00262             rc = 1;
00263             goto exit;
00264         }
00265     }
00266     
00267     /* Parse the spec file */
00268 #define _anyarch(_f)    \
00269 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
00270     if (parseSpec(&spec, specURL, ba->rootdir, buildRootURL, 0, passPhrase,
00271                 cookie, _anyarch(buildAmount), ba->force)) {
00272         rc = 1;
00273         goto exit;
00274     }
00275 #undef  _anyarch
00276 
00277     /* Assemble source header from parsed components */
00278     initSourceHeader(spec);
00279 
00280     /* Check build prerequisites */
00281     if (!ba->noDeps && checkSpec(spec->sourceHeader)) {
00282         rc = 1;
00283         goto exit;
00284     }
00285 
00286     if (buildSpec(spec, buildAmount, ba->noBuild)) {
00287         rc = 1;
00288         goto exit;
00289     }
00290     
00291     if (ba->buildMode == 't')
00292         (void) Unlink(specURL);
00293     rc = 0;
00294 
00295 exit:
00296     spec = freeSpec(spec);
00297     buildRootURL = _free(buildRootURL);
00298     return rc;
00299 }
00300 
00301 int build(const char * arg, BTA_t ba,
00302         const char * passPhrase, char * cookie, const char * rcfile)
00303 {
00304     char *t, *te;
00305     int rc = 0;
00306     char * targets = ba->targets;
00307 #define buildCleanMask  (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
00308     int cleanFlags = ba->buildAmount & buildCleanMask;
00309 
00310     if (targets == NULL) {
00311         rc =  buildForTarget(arg, ba, passPhrase, cookie);
00312         goto exit;
00313     }
00314 
00315     /* parse up the build operators */
00316 
00317     printf(_("Building target platforms: %s\n"), targets);
00318 
00319     ba->buildAmount &= ~buildCleanMask;
00320     for (t = targets; *t != '\0'; t = te) {
00321         char *target;
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         else    /* XXX Perform clean-up after last target build. */
00330             ba->buildAmount |= cleanFlags;
00331 
00332         printf(_("Building for target %s\n"), target);
00333 
00334         /* Read in configuration for target. */
00335         rpmFreeMacros(NULL);
00336         (void) rpmReadConfigFiles(rcfile, target);
00337         rc = buildForTarget(arg, ba, passPhrase, cookie);
00338         if (rc)
00339             break;
00340     }
00341 
00342 exit:
00343     /* Restore original configuration. */
00344     rpmFreeMacros(NULL);
00345     (void) rpmReadConfigFiles(rcfile, NULL);
00346 
00347     return rc;
00348 }

Generated on Thu Apr 18 17:34:36 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002