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