rpm 5.3.7
|
00001 00005 #include "system.h" 00006 00007 #include <rpmio.h> 00008 #include <rpmiotypes.h> 00009 #include <rpmcb.h> 00010 #include <rpmurl.h> 00011 00012 #include <rpmtypes.h> 00013 #include <rpmtag.h> 00014 00015 #include <rpmbuild.h> 00016 00017 #include "rpmps.h" 00018 #include "rpmte.h" 00019 #include "rpmts.h" 00020 00021 #include "build.h" 00022 00023 #include <rpmcli.h> 00024 00025 #include "debug.h" 00026 00027 /*@access rpmts @*/ /* XXX compared with NULL @*/ 00028 /*@access rpmdb @*/ /* XXX compared with NULL @*/ 00029 /*@access FD_t @*/ /* XXX compared with NULL @*/ 00030 00033 static int checkSpec(rpmts ts, Header h) 00034 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00035 /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/ 00036 { 00037 int rc; 00038 00039 if (!headerIsEntry(h, RPMTAG_REQUIRENAME) 00040 && !headerIsEntry(h, RPMTAG_CONFLICTNAME)) 00041 return 0; 00042 00043 rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL); 00044 00045 rc = rpmcliInstallProblems(ts, _("Failed build dependencies"), rpmtsCheck(ts)); 00046 00047 /* XXX nuke the added package. */ 00048 rpmtsClean(ts); 00049 00050 return rc; 00051 } 00052 00053 /* 00054 * Kurwa, durni ameryka?ce sobe zawsze my?l?, ?e ca?y ?wiat mówi po 00055 * angielsku... 00056 */ 00057 /* XXX this is still a dumb test but at least it's i18n aware */ 00060 static int isSpecFile(const char * specfile) 00061 /*@globals h_errno, fileSystem, internalState @*/ 00062 /*@modifies fileSystem, internalState @*/ 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"); 00071 if (fd == NULL || Ferror(fd)) { 00072 rpmlog(RPMLOG_ERR, _("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 (void) 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 /*@switchbreak@*/ break; 00086 case ':': 00087 checking = 0; 00088 /*@switchbreak@*/ break; 00089 /*@-boundsread@*/ 00090 default: 00091 if (checking && !(isprint(*s) || isspace(*s))) return 0; 00092 /*@switchbreak@*/ break; 00093 /*@=boundsread@*/ 00094 } 00095 } 00096 return 1; 00097 } 00098 00101 /*@-boundswrite@*/ 00102 static int buildForTarget(rpmts ts, BTA_t ba) 00103 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00104 /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/ 00105 { 00106 const char * passPhrase = ba->passPhrase; 00107 const char * cookie = ba->cookie; 00108 int buildAmount = ba->buildAmount; 00109 const char * specFile = NULL; 00110 const char * specURL = NULL; 00111 int specut; 00112 const char * s; 00113 char * se; 00114 const char * arg = ba->specFile; 00115 size_t nb = strlen(arg) + BUFSIZ; 00116 char * buf = alloca(nb); 00117 Spec spec = NULL; 00118 int verify = ((ba->buildAmount & RPMBUILD_TRACK) ? 0 : 1); 00119 int xx; 00120 int rc; 00121 00122 if (ba->buildMode == 't') { 00123 static const char * sfpats[] = { "Specfile", "\\*.spec", NULL }; 00124 static const char _specfn[] = "%{mkstemp:%{_specdir}/rpm-spec.XXXXXX}"; 00125 char * tmpSpecFile = (char *) rpmGetPath(_specfn, NULL); 00126 FILE *fp; 00127 int bingo = 0; 00128 int i; 00129 00130 for (i = 0; sfpats[i]; i++) { 00131 se = rpmExpand("%{uncompress: %{u2p:", arg, "}}", 00132 " | %{__tar} -xOvf - %{?__tar_wildcards} ", sfpats[i], 00133 " 2>&1 > '", tmpSpecFile, "'", NULL); 00134 fp = popen(se, "r"); 00135 se = _free(se); 00136 if (fp== NULL) 00137 continue; 00138 s = fgets(buf, nb - 1, fp); 00139 xx = pclose(fp); 00140 if (!s || !*s || strstr(s, ": Not found in archive")) 00141 continue; 00142 bingo = 1; 00143 break; 00144 } 00145 if (!bingo) { 00146 rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg); 00147 xx = Unlink(tmpSpecFile); 00148 tmpSpecFile = _free(tmpSpecFile); 00149 return 1; 00150 } 00151 00152 s = se = basename(buf); 00153 se += strlen(se); 00154 while (--se > s && strchr("\r\n", *se) != NULL) 00155 *se = '\0'; 00156 specURL = rpmGetPath("%{_specdir}/", s, NULL); 00157 specut = urlPath(specURL, &specFile); 00158 xx = Rename(tmpSpecFile, specFile); 00159 if (xx) { 00160 rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"), 00161 tmpSpecFile, s); 00162 (void) Unlink(tmpSpecFile); 00163 } 00164 tmpSpecFile = _free(tmpSpecFile); 00165 if (xx) 00166 return 1; 00167 00168 se = buf; *se = '\0'; 00169 se = stpcpy(se, "_sourcedir "); 00170 (void) urlPath(arg, &s); 00171 if (*s != '/') { 00172 if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL) 00173 se += strlen(se); 00174 else 00175 se = stpcpy(se, "."); 00176 } else 00177 se = stpcpy(se, dirname(strcpy(se, s))); 00178 while (se > buf && se[-1] == '/') 00179 *se-- = '0'; 00180 rpmCleanPath(buf + sizeof("_sourcedir ") - 1); 00181 rpmDefineMacro(NULL, buf, RMIL_TARBALL); 00182 } else { 00183 specut = urlPath(arg, &s); 00184 se = buf; *se = '\0'; 00185 if (*s != '/') { 00186 if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL) 00187 se += strlen(se); 00188 else 00189 se = stpcpy(se, "."); 00190 *se++ = '/'; 00191 se += strlen(strcpy(se,strcpy(se, s))); 00192 } else 00193 se = stpcpy(se, s); 00194 specURL = rpmGetPath(buf, NULL); 00195 specut = urlPath(specURL, &specFile); 00196 } 00197 00198 if (specut != URL_IS_DASH) { 00199 struct stat sb; 00200 if (Stat(specURL, &sb) < 0) { 00201 rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specURL); 00202 rc = 1; 00203 goto exit; 00204 } 00205 if (! S_ISREG(sb.st_mode)) { 00206 rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"), 00207 specURL); 00208 rc = 1; 00209 goto exit; 00210 } 00211 00212 /* Try to verify that the file is actually a specfile */ 00213 if (!isSpecFile(specURL)) { 00214 rpmlog(RPMLOG_ERR, 00215 _("File %s does not appear to be a specfile.\n"), specURL); 00216 rc = 1; 00217 goto exit; 00218 } 00219 } 00220 00221 /* Parse the spec file */ 00222 #define _anyarch(_f) \ 00223 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0) 00224 if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase, 00225 cookie, _anyarch(buildAmount), 0, verify)) 00226 { 00227 rc = 1; 00228 goto exit; 00229 } 00230 #undef _anyarch 00231 if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) { 00232 rc = 1; 00233 goto exit; 00234 } 00235 00236 /* Assemble source header from parsed components */ 00237 xx = initSourceHeader(spec, NULL); 00238 00239 /* Check build prerequisites */ 00240 if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) { 00241 rc = 1; 00242 goto exit; 00243 } 00244 00245 if (buildSpec(ts, spec, buildAmount, ba->noBuild)) { 00246 rc = 1; 00247 goto exit; 00248 } 00249 00250 if (ba->buildMode == 't') 00251 (void) Unlink(specURL); 00252 rc = 0; 00253 00254 exit: 00255 spec = freeSpec(spec); 00256 specURL = _free(specURL); 00257 return rc; 00258 } 00259 /*@=boundswrite@*/ 00260 00261 int build(rpmts ts, BTA_t ba, const char * rcfile) 00262 { 00263 const char *t, *te; 00264 int rc = 0; 00265 const char * targets = rpmcliTargets; 00266 char *target; 00267 #define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC) 00268 int cleanFlags = ba->buildAmount & buildCleanMask; 00269 rpmVSFlags vsflags, ovsflags; 00270 int nbuilds = 0; 00271 00272 vsflags = rpmExpandNumeric("%{_vsflags_build}"); 00273 if (ba->qva_flags & VERIFY_DIGEST) 00274 vsflags |= _RPMVSF_NODIGESTS; 00275 if (ba->qva_flags & VERIFY_SIGNATURE) 00276 vsflags |= _RPMVSF_NOSIGNATURES; 00277 if (ba->qva_flags & VERIFY_HDRCHK) 00278 vsflags |= RPMVSF_NOHDRCHK; 00279 ovsflags = rpmtsSetVSFlags(ts, vsflags); 00280 00281 if (targets == NULL) { 00282 rc = buildForTarget(ts, ba); 00283 nbuilds++; 00284 goto exit; 00285 } 00286 00287 /* parse up the build operators */ 00288 00289 printf(_("Building target platforms: %s\n"), targets); 00290 00291 ba->buildAmount &= ~buildCleanMask; 00292 for (t = targets; *t != '\0'; t = te) { 00293 /* Parse out next target platform. */ 00294 if ((te = strchr(t, ',')) == NULL) 00295 te = t + strlen(t); 00296 target = alloca(te-t+1); 00297 strncpy(target, t, (te-t)); 00298 target[te-t] = '\0'; 00299 if (*te != '\0') 00300 te++; 00301 else /* XXX Perform clean-up after last target build. */ 00302 ba->buildAmount |= cleanFlags; 00303 00304 rpmlog(RPMLOG_DEBUG, _(" target platform: %s\n"), target); 00305 00306 /* Read in configuration for target. */ 00307 if (t != targets) { 00308 rpmFreeMacros(NULL); 00309 rpmFreeRpmrc(); 00310 (void) rpmReadConfigFiles(rcfile, target); 00311 } 00312 rc = buildForTarget(ts, ba); 00313 nbuilds++; 00314 if (rc) 00315 break; 00316 } 00317 00318 exit: 00319 /* Restore original configuration. */ 00320 if (nbuilds > 1) { 00321 t = targets; 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 rpmFreeMacros(NULL); 00330 rpmFreeRpmrc(); 00331 (void) rpmReadConfigFiles(rcfile, target); 00332 } 00333 vsflags = rpmtsSetVSFlags(ts, ovsflags); 00334 00335 return rc; 00336 }