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

Generated at Thu Apr 19 15:29:41 2001 for rpm by doxygen1.2.6-20010408 written by Dimitri van Heesch, © 1997-2001