00001
00005 #include "system.h"
00006
00007 #include <libgen.h>
00008 #include <errno.h>
00009 #include <ctype.h>
00010
00011 #include <rpm/rpmcli.h>
00012 #include <rpm/rpmtag.h>
00013 #include <rpm/rpmlib.h>
00014 #include <rpm/rpmbuild.h>
00015
00016 #include <rpm/rpmps.h>
00017 #include <rpm/rpmte.h>
00018 #include <rpm/rpmts.h>
00019 #include <rpm/rpmfileutil.h>
00020 #include <rpm/rpmlog.h>
00021 #include <lib/misc.h>
00022
00023 #include "build.h"
00024 #include "debug.h"
00025
00028 static int checkSpec(rpmts ts, Header h)
00029 {
00030 rpmps ps;
00031 int rc;
00032
00033 if (!headerIsEntry(h, RPMTAG_REQUIRENAME)
00034 && !headerIsEntry(h, RPMTAG_CONFLICTNAME))
00035 return 0;
00036
00037 rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
00038
00039 rc = rpmtsCheck(ts);
00040
00041 ps = rpmtsProblems(ts);
00042 if (rc == 0 && rpmpsNumProblems(ps) > 0) {
00043 rpmlog(RPMLOG_ERR, _("Failed build dependencies:\n"));
00044 rpmpsPrint(NULL, ps);
00045 rc = 1;
00046 }
00047 ps = rpmpsFree(ps);
00048
00049
00050 rpmtsClean(ts);
00051
00052 return rc;
00053 }
00054
00057 static int isSpecFile(const char * specfile)
00058 {
00059 char buf[256];
00060 const char * s;
00061 FILE * f;
00062 int count;
00063 int checking;
00064
00065 f = fopen(specfile, "r");
00066 if (f == NULL || ferror(f)) {
00067 rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"),
00068 specfile, strerror(errno));
00069 return 0;
00070 }
00071 count = fread(buf, sizeof(buf[0]), sizeof(buf), f);
00072 (void) fclose(f);
00073
00074 if (count == 0)
00075 return 0;
00076
00077 checking = 1;
00078 for (s = buf; count--; s++) {
00079 switch (*s) {
00080 case '\r':
00081 case '\n':
00082 checking = 1;
00083 break;
00084 case ':':
00085 checking = 0;
00086 break;
00087 default:
00088 #if 0
00089 if (checking && !(isprint(*s) || isspace(*s))) return 0;
00090 break;
00091 #else
00092 if (checking && !(isprint(*s) || isspace(*s)) && *(unsigned char *)s < 32) return 0;
00093 break;
00094 #endif
00095 }
00096 }
00097 return 1;
00098 }
00099
00100
00101
00102
00103
00104 static char * getTarSpec(const char *arg)
00105 {
00106 char *specFile = NULL;
00107 char *specDir;
00108 char *specBase;
00109 char *tmpSpecFile;
00110 const char **try;
00111 char tarbuf[BUFSIZ];
00112 int gotspec = 0, res;
00113 static const char *tryspec[] = { "Specfile", "\\*.spec", NULL };
00114
00115 specDir = rpmGetPath("%{_specdir}", NULL);
00116 tmpSpecFile = rpmGetPath("%{_specdir}/", "rpm-spec.XXXXXX", NULL);
00117
00118 (void) close(mkstemp(tmpSpecFile));
00119
00120 for (try = tryspec; *try != NULL; try++) {
00121 FILE *fp;
00122 char *cmd;
00123
00124 cmd = rpmExpand("%{uncompress: ", arg, "} | ",
00125 "%{__tar} xOvf - --wildcards ", *try,
00126 " 2>&1 > ", tmpSpecFile, NULL);
00127
00128 if (!(fp = popen(cmd, "r"))) {
00129 rpmlog(RPMLOG_ERR, _("Failed to open tar pipe: %m\n"));
00130 } else {
00131 char *fok = fgets(tarbuf, sizeof(tarbuf) - 1, fp);
00132 pclose(fp);
00133 gotspec = (fok != NULL) && isSpecFile(tmpSpecFile);
00134 }
00135
00136 if (!gotspec)
00137 unlink(tmpSpecFile);
00138 free(cmd);
00139 }
00140
00141 if (!gotspec) {
00142 rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg);
00143 goto exit;
00144 }
00145
00146 specBase = basename(tarbuf);
00147
00148 specBase[strlen(specBase)-1] = '\0';
00149
00150 rasprintf(&specFile, "%s/%s", specDir, specBase);
00151 res = rename(tmpSpecFile, specFile);
00152
00153 if (res) {
00154 rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"),
00155 tmpSpecFile, specFile);
00156 free(specFile);
00157 specFile = NULL;
00158 } else {
00159
00160 mode_t mask;
00161 umask(mask = umask(0));
00162 (void) chmod(specFile, 0666 & ~mask);
00163 }
00164
00165 exit:
00166 (void) unlink(tmpSpecFile);
00167 free(tmpSpecFile);
00168 free(specDir);
00169 return specFile;
00170 }
00171
00174 static int buildForTarget(rpmts ts, const char * arg, BTA_t ba)
00175 {
00176 const char * passPhrase = ba->passPhrase;
00177 const char * cookie = ba->cookie;
00178 int buildAmount = ba->buildAmount;
00179 char * buildRootURL = NULL;
00180 char * specFile = NULL;
00181 rpmSpec spec = NULL;
00182 int rc = 1;
00183
00184 #ifndef DYING
00185 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
00186 #endif
00187
00188 if (ba->buildRootOverride)
00189 buildRootURL = rpmGenPath(NULL, ba->buildRootOverride, NULL);
00190
00191
00192 const char * buildtree = "%{_topdir}:%{_specdir}:%{_sourcedir}:%{_builddir}:%{_rpmdir}:%{_srcrpmdir}:%{_buildrootdir}";
00193 const char * rootdir = rpmtsRootDir(ts);
00194 if (rpmMkdirs(!rstreq(rootdir, "/") ? rootdir : NULL , buildtree)) {
00195 goto exit;
00196 }
00197
00198 if (ba->buildMode == 't') {
00199 char *srcdir = NULL, *dir;
00200
00201 specFile = getTarSpec(arg);
00202 if (!specFile)
00203 goto exit;
00204
00205
00206
00207 if (*arg != '/') {
00208 dir = rpmGetCwd();
00209 rstrscat(&dir, "/", arg, NULL);
00210 } else {
00211 dir = xstrdup(arg);
00212 }
00213 srcdir = dirname(dir);
00214 addMacro(NULL, "_sourcedir", NULL, srcdir, RMIL_TARBALL);
00215 free(dir);
00216 } else {
00217 specFile = xstrdup(arg);
00218 }
00219
00220 if (*specFile != '/') {
00221 char *cwd = rpmGetCwd();
00222 char *s = NULL;
00223 rasprintf(&s, "%s/%s", cwd, arg);
00224 free(cwd);
00225 free(specFile);
00226 specFile = s;
00227 }
00228
00229 struct stat st;
00230 if (stat(specFile, &st) < 0) {
00231 rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specFile);
00232 goto exit;
00233 }
00234 if (! S_ISREG(st.st_mode)) {
00235 rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"), specFile);
00236 goto exit;
00237 }
00238
00239
00240 if (!isSpecFile(specFile)) {
00241 rpmlog(RPMLOG_ERR,
00242 _("File %s does not appear to be a specfile.\n"), specFile);
00243 goto exit;
00244 }
00245
00246
00247 if (ba->buildAmount == RPMBUILD_RMSPEC) {
00248 rc = unlink(specFile);
00249 goto exit;
00250 }
00251
00252
00253 #define _anyarch(_f) \
00254 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
00255 if (parseSpec(ts, specFile, ba->rootdir, buildRootURL, 0, passPhrase,
00256 cookie, _anyarch(buildAmount), ba->force))
00257 {
00258 goto exit;
00259 }
00260 #undef _anyarch
00261 if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
00262 goto exit;
00263 }
00264
00265 if ( ba->buildAmount&RPMBUILD_RMSOURCE && !(ba->buildAmount&~(RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)) ) {
00266 rc = doRmSource(spec);
00267 if ( rc == RPMRC_OK && ba->buildAmount&RPMBUILD_RMSPEC )
00268 rc = unlink(specFile);
00269 goto exit;
00270 }
00271
00272
00273 initSourceHeader(spec);
00274
00275
00276 if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
00277 goto exit;
00278 }
00279
00280 if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
00281 goto exit;
00282 }
00283
00284 if (ba->buildMode == 't')
00285 (void) unlink(specFile);
00286 rc = 0;
00287
00288 exit:
00289 free(specFile);
00290 freeSpec(spec);
00291 free(buildRootURL);
00292 return rc;
00293 }
00294
00295 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile)
00296 {
00297 char *t, *te;
00298 int rc = 0;
00299 char * targets = ba->targets;
00300 #define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
00301 int cleanFlags = ba->buildAmount & buildCleanMask;
00302 rpmVSFlags vsflags, ovsflags;
00303
00304 vsflags = rpmExpandNumeric("%{_vsflags_build}");
00305 if (ba->qva_flags & VERIFY_DIGEST)
00306 vsflags |= _RPMVSF_NODIGESTS;
00307 if (ba->qva_flags & VERIFY_SIGNATURE)
00308 vsflags |= _RPMVSF_NOSIGNATURES;
00309 if (ba->qva_flags & VERIFY_HDRCHK)
00310 vsflags |= RPMVSF_NOHDRCHK;
00311 ovsflags = rpmtsSetVSFlags(ts, vsflags);
00312
00313 if (targets == NULL) {
00314 rc = buildForTarget(ts, arg, ba);
00315 goto exit;
00316 }
00317
00318
00319
00320 printf(_("Building target platforms: %s\n"), targets);
00321
00322 ba->buildAmount &= ~buildCleanMask;
00323 for (t = targets; *t != '\0'; t = te) {
00324 char *target;
00325 if ((te = strchr(t, ',')) == NULL)
00326 te = t + strlen(t);
00327 target = xmalloc(te-t+1);
00328 strncpy(target, t, (te-t));
00329 target[te-t] = '\0';
00330 if (*te != '\0')
00331 te++;
00332 else
00333 ba->buildAmount |= cleanFlags;
00334
00335 printf(_("Building for target %s\n"), target);
00336
00337
00338 rpmFreeMacros(NULL);
00339 rpmFreeRpmrc();
00340 (void) rpmReadConfigFiles(rcfile, target);
00341 free(target);
00342 rc = buildForTarget(ts, arg, ba);
00343 if (rc)
00344 break;
00345 }
00346
00347 exit:
00348 vsflags = rpmtsSetVSFlags(ts, ovsflags);
00349
00350 rpmFreeMacros(NULL);
00351 rpmFreeRpmrc();
00352 (void) rpmReadConfigFiles(rcfile, NULL);
00353
00354 return rc;
00355 }