00001
00005 #include "system.h"
00006
00007 #include <rpmio.h>
00008 #include <rpmcli.h>
00009 #include <rpmbuild.h>
00010
00011 #include "rpmps.h"
00012 #include "rpmte.h"
00013 #include "rpmts.h"
00014
00015 #include "build.h"
00016 #include "debug.h"
00017
00018
00019
00020
00021
00024 static int checkSpec(rpmts ts, Header h)
00025
00026
00027 {
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 = rpmcliInstallProblems(ts, _("Failed build dependencies"), rpmtsCheck(ts));
00037
00038
00039 rpmtsClean(ts);
00040
00041 return rc;
00042 }
00043
00044
00045
00046
00047
00048
00051 static int isSpecFile(const char * specfile)
00052
00053
00054 {
00055 char buf[256];
00056 const char * s;
00057 FD_t fd;
00058 int count;
00059 int checking;
00060
00061 fd = Fopen(specfile, "r");
00062 if (fd == NULL || Ferror(fd)) {
00063 rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"),
00064 specfile, Fstrerror(fd));
00065 return 0;
00066 }
00067 count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
00068 (void) Fclose(fd);
00069
00070 checking = 1;
00071 for (s = buf; count--; s++) {
00072 switch (*s) {
00073 case '\r':
00074 case '\n':
00075 checking = 1;
00076 break;
00077 case ':':
00078 checking = 0;
00079 break;
00080
00081 default:
00082 if (checking && !(isprint(*s) || isspace(*s))) return 0;
00083 break;
00084
00085 }
00086 }
00087 return 1;
00088 }
00089
00092
00093 static int buildForTarget(rpmts ts, const char * arg, BTA_t ba)
00094
00095
00096 {
00097 const char * passPhrase = ba->passPhrase;
00098 const char * cookie = ba->cookie;
00099 int buildAmount = ba->buildAmount;
00100 const char * specFile = NULL;
00101 const char * specURL = NULL;
00102 int specut;
00103 const char * s;
00104 char * se;
00105 size_t nb = strlen(arg) + BUFSIZ;
00106 char * buf = alloca(nb);
00107 Spec spec = NULL;
00108 int verify = ((ba->buildAmount & RPMBUILD_TRACK) ? 0 : 1);
00109 int xx;
00110 int rc;
00111
00112 #ifndef DYING
00113 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
00114 #endif
00115
00116 if (ba->buildMode == 't') {
00117 static const char * sfpats[] = { "Specfile", "\\*.spec", NULL };
00118 static const char _specfn[] = "%{mkstemp:%{_specdir}/rpm-spec.XXXXXX}";
00119 char * tmpSpecFile = (char *) rpmGetPath(_specfn, NULL);
00120 FILE *fp;
00121 int bingo = 0;
00122 int i;
00123
00124 for (i = 0; sfpats[i]; i++) {
00125 se = rpmExpand("%{uncompress: %{u2p:", arg, "}}",
00126 " | %{__tar} -xOvf - %{?__tar_wildcards} ", sfpats[i],
00127 " 2>&1 > '", tmpSpecFile, "'", NULL);
00128 fp = popen(se, "r");
00129 se = _free(se);
00130 if (fp== NULL)
00131 continue;
00132 s = fgets(buf, nb - 1, fp);
00133 xx = pclose(fp);
00134 if (!s || !*s || strstr(s, ": Not found in archive"))
00135 continue;
00136 bingo = 1;
00137 break;
00138 }
00139 if (!bingo) {
00140 rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg);
00141 xx = Unlink(tmpSpecFile);
00142 tmpSpecFile = _free(tmpSpecFile);
00143 return 1;
00144 }
00145
00146 s = se = basename(buf);
00147 se += strlen(se);
00148 while (--se > s && strchr("\r\n", *se) != NULL)
00149 *se = '\0';
00150 specURL = rpmGetPath("%{_specdir}/", s, NULL);
00151 specut = urlPath(specURL, &specFile);
00152 xx = Rename(tmpSpecFile, specFile);
00153 if (xx) {
00154 rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"),
00155 tmpSpecFile, s);
00156 (void) Unlink(tmpSpecFile);
00157 }
00158 tmpSpecFile = _free(tmpSpecFile);
00159 if (xx)
00160 return 1;
00161
00162 se = buf; *se = '\0';
00163 se = stpcpy(se, "_sourcedir ");
00164 (void) urlPath(arg, &s);
00165 if (*s != '/') {
00166 if (getcwd(se, nb - sizeof("_sourcedir ")) > 0)
00167 se += strlen(se);
00168 else
00169 se = stpcpy(se, ".");
00170 } else
00171 se = stpcpy(se, dirname(strcpy(se, s)));
00172 while (se > buf && se[-1] == '/')
00173 *se-- = '0';
00174 rpmCleanPath(buf + sizeof("_sourcedir ") - 1);
00175 rpmDefineMacro(NULL, buf, RMIL_TARBALL);
00176 } else {
00177 specut = urlPath(arg, &s);
00178 se = buf; *se = '\0';
00179 if (*s != '/') {
00180 if (getcwd(se, nb - sizeof("_sourcedir ")) > 0)
00181 se += strlen(se);
00182 else
00183 se = stpcpy(se, ".");
00184 *se++ = '/';
00185 se += strlen(strcpy(se,strcpy(se, s)));
00186 } else
00187 se = stpcpy(se, s);
00188 specURL = rpmGetPath(buf, NULL);
00189 specut = urlPath(specURL, &specFile);
00190 }
00191
00192 if (specut != URL_IS_DASH) {
00193 struct stat sb;
00194 if (Stat(specURL, &sb) < 0) {
00195 rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specURL);
00196 rc = 1;
00197 goto exit;
00198 }
00199 if (! S_ISREG(sb.st_mode)) {
00200 rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"),
00201 specURL);
00202 rc = 1;
00203 goto exit;
00204 }
00205
00206
00207 if (!isSpecFile(specURL)) {
00208 rpmlog(RPMLOG_ERR,
00209 _("File %s does not appear to be a specfile.\n"), specURL);
00210 rc = 1;
00211 goto exit;
00212 }
00213 }
00214
00215
00216 #define _anyarch(_f) \
00217 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
00218 if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase,
00219 cookie, _anyarch(buildAmount), 0, verify))
00220 {
00221 rc = 1;
00222 goto exit;
00223 }
00224 #undef _anyarch
00225 if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
00226 rc = 1;
00227 goto exit;
00228 }
00229
00230
00231 xx = initSourceHeader(spec, NULL);
00232
00233
00234 if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
00235 rc = 1;
00236 goto exit;
00237 }
00238
00239 if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
00240 rc = 1;
00241 goto exit;
00242 }
00243
00244 if (ba->buildMode == 't')
00245 (void) Unlink(specURL);
00246 rc = 0;
00247
00248 exit:
00249 spec = freeSpec(spec);
00250 specURL = _free(specURL);
00251 return rc;
00252 }
00253
00254
00255 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile)
00256 {
00257 const char *t, *te;
00258 int rc = 0;
00259 const char * targets = rpmcliTargets;
00260 char *target;
00261 #define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
00262 int cleanFlags = ba->buildAmount & buildCleanMask;
00263 rpmVSFlags vsflags, ovsflags;
00264 int nbuilds = 0;
00265
00266 vsflags = rpmExpandNumeric("%{_vsflags_build}");
00267 if (ba->qva_flags & VERIFY_DIGEST)
00268 vsflags |= _RPMVSF_NODIGESTS;
00269 if (ba->qva_flags & VERIFY_SIGNATURE)
00270 vsflags |= _RPMVSF_NOSIGNATURES;
00271 if (ba->qva_flags & VERIFY_HDRCHK)
00272 vsflags |= RPMVSF_NOHDRCHK;
00273 ovsflags = rpmtsSetVSFlags(ts, vsflags);
00274
00275 if (targets == NULL) {
00276 rc = buildForTarget(ts, arg, ba);
00277 nbuilds++;
00278 goto exit;
00279 }
00280
00281
00282
00283 printf(_("Building target platforms: %s\n"), targets);
00284
00285 ba->buildAmount &= ~buildCleanMask;
00286 for (t = targets; *t != '\0'; t = te) {
00287
00288 if ((te = strchr(t, ',')) == NULL)
00289 te = t + strlen(t);
00290 target = alloca(te-t+1);
00291 strncpy(target, t, (te-t));
00292 target[te-t] = '\0';
00293 if (*te != '\0')
00294 te++;
00295 else
00296 ba->buildAmount |= cleanFlags;
00297
00298 rpmlog(RPMLOG_DEBUG, _(" target platform: %s\n"), target);
00299
00300
00301 if (t != targets) {
00302 rpmFreeMacros(NULL);
00303 rpmFreeRpmrc();
00304 (void) rpmReadConfigFiles(rcfile, target);
00305 }
00306 rc = buildForTarget(ts, arg, ba);
00307 nbuilds++;
00308 if (rc)
00309 break;
00310 }
00311
00312 exit:
00313
00314 if (nbuilds > 1) {
00315 t = targets;
00316 if ((te = strchr(t, ',')) == NULL)
00317 te = t + strlen(t);
00318 target = alloca(te-t+1);
00319 strncpy(target, t, (te-t));
00320 target[te-t] = '\0';
00321 if (*te != '\0')
00322 te++;
00323 rpmFreeMacros(NULL);
00324 rpmFreeRpmrc();
00325 (void) rpmReadConfigFiles(rcfile, target);
00326 }
00327 vsflags = rpmtsSetVSFlags(ts, ovsflags);
00328
00329 return rc;
00330 }