rpm
5.2.1
|
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, const char * arg, 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 size_t nb = strlen(arg) + BUFSIZ; 00115 char * buf = alloca(nb); 00116 Spec spec = NULL; 00117 int verify = ((ba->buildAmount & RPMBUILD_TRACK) ? 0 : 1); 00118 int xx; 00119 int rc; 00120 00121 if (ba->buildMode == 't') { 00122 static const char * sfpats[] = { "Specfile", "\\*.spec", NULL }; 00123 static const char _specfn[] = "%{mkstemp:%{_specdir}/rpm-spec.XXXXXX}"; 00124 char * tmpSpecFile = (char *) rpmGetPath(_specfn, NULL); 00125 FILE *fp; 00126 int bingo = 0; 00127 int i; 00128 00129 for (i = 0; sfpats[i]; i++) { 00130 se = rpmExpand("%{uncompress: %{u2p:", arg, "}}", 00131 " | %{__tar} -xOvf - %{?__tar_wildcards} ", sfpats[i], 00132 " 2>&1 > '", tmpSpecFile, "'", NULL); 00133 fp = popen(se, "r"); 00134 se = _free(se); 00135 if (fp== NULL) 00136 continue; 00137 s = fgets(buf, nb - 1, fp); 00138 xx = pclose(fp); 00139 if (!s || !*s || strstr(s, ": Not found in archive")) 00140 continue; 00141 bingo = 1; 00142 break; 00143 } 00144 if (!bingo) { 00145 rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg); 00146 xx = Unlink(tmpSpecFile); 00147 tmpSpecFile = _free(tmpSpecFile); 00148 return 1; 00149 } 00150 00151 s = se = basename(buf); 00152 se += strlen(se); 00153 while (--se > s && strchr("\r\n", *se) != NULL) 00154 *se = '\0'; 00155 specURL = rpmGetPath("%{_specdir}/", s, NULL); 00156 specut = urlPath(specURL, &specFile); 00157 xx = Rename(tmpSpecFile, specFile); 00158 if (xx) { 00159 rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"), 00160 tmpSpecFile, s); 00161 (void) Unlink(tmpSpecFile); 00162 } 00163 tmpSpecFile = _free(tmpSpecFile); 00164 if (xx) 00165 return 1; 00166 00167 se = buf; *se = '\0'; 00168 se = stpcpy(se, "_sourcedir "); 00169 (void) urlPath(arg, &s); 00170 if (*s != '/') { 00171 if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL) 00172 se += strlen(se); 00173 else 00174 se = stpcpy(se, "."); 00175 } else 00176 se = stpcpy(se, dirname(strcpy(se, s))); 00177 while (se > buf && se[-1] == '/') 00178 *se-- = '0'; 00179 rpmCleanPath(buf + sizeof("_sourcedir ") - 1); 00180 rpmDefineMacro(NULL, buf, RMIL_TARBALL); 00181 } else { 00182 specut = urlPath(arg, &s); 00183 se = buf; *se = '\0'; 00184 if (*s != '/') { 00185 if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL) 00186 se += strlen(se); 00187 else 00188 se = stpcpy(se, "."); 00189 *se++ = '/'; 00190 se += strlen(strcpy(se,strcpy(se, s))); 00191 } else 00192 se = stpcpy(se, s); 00193 specURL = rpmGetPath(buf, NULL); 00194 specut = urlPath(specURL, &specFile); 00195 } 00196 00197 if (specut != URL_IS_DASH) { 00198 struct stat sb; 00199 if (Stat(specURL, &sb) < 0) { 00200 rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specURL); 00201 rc = 1; 00202 goto exit; 00203 } 00204 if (! S_ISREG(sb.st_mode)) { 00205 rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"), 00206 specURL); 00207 rc = 1; 00208 goto exit; 00209 } 00210 00211 /* Try to verify that the file is actually a specfile */ 00212 if (!isSpecFile(specURL)) { 00213 rpmlog(RPMLOG_ERR, 00214 _("File %s does not appear to be a specfile.\n"), specURL); 00215 rc = 1; 00216 goto exit; 00217 } 00218 } 00219 00220 /* Parse the spec file */ 00221 #define _anyarch(_f) \ 00222 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0) 00223 if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase, 00224 cookie, _anyarch(buildAmount), 0, verify)) 00225 { 00226 rc = 1; 00227 goto exit; 00228 } 00229 #undef _anyarch 00230 if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) { 00231 rc = 1; 00232 goto exit; 00233 } 00234 00235 /* Assemble source header from parsed components */ 00236 xx = initSourceHeader(spec, NULL); 00237 00238 /* Check build prerequisites */ 00239 if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) { 00240 rc = 1; 00241 goto exit; 00242 } 00243 00244 if (buildSpec(ts, spec, buildAmount, ba->noBuild)) { 00245 rc = 1; 00246 goto exit; 00247 } 00248 00249 if (ba->buildMode == 't') 00250 (void) Unlink(specURL); 00251 rc = 0; 00252 00253 exit: 00254 spec = freeSpec(spec); 00255 specURL = _free(specURL); 00256 return rc; 00257 } 00258 /*@=boundswrite@*/ 00259 00260 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile) 00261 { 00262 const char *t, *te; 00263 int rc = 0; 00264 const char * targets = rpmcliTargets; 00265 char *target; 00266 #define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC) 00267 int cleanFlags = ba->buildAmount & buildCleanMask; 00268 rpmVSFlags vsflags, ovsflags; 00269 int nbuilds = 0; 00270 00271 vsflags = rpmExpandNumeric("%{_vsflags_build}"); 00272 if (ba->qva_flags & VERIFY_DIGEST) 00273 vsflags |= _RPMVSF_NODIGESTS; 00274 if (ba->qva_flags & VERIFY_SIGNATURE) 00275 vsflags |= _RPMVSF_NOSIGNATURES; 00276 if (ba->qva_flags & VERIFY_HDRCHK) 00277 vsflags |= RPMVSF_NOHDRCHK; 00278 ovsflags = rpmtsSetVSFlags(ts, vsflags); 00279 00280 if (targets == NULL) { 00281 rc = buildForTarget(ts, arg, ba); 00282 nbuilds++; 00283 goto exit; 00284 } 00285 00286 /* parse up the build operators */ 00287 00288 printf(_("Building target platforms: %s\n"), targets); 00289 00290 ba->buildAmount &= ~buildCleanMask; 00291 for (t = targets; *t != '\0'; t = te) { 00292 /* Parse out next target platform. */ 00293 if ((te = strchr(t, ',')) == NULL) 00294 te = t + strlen(t); 00295 target = alloca(te-t+1); 00296 strncpy(target, t, (te-t)); 00297 target[te-t] = '\0'; 00298 if (*te != '\0') 00299 te++; 00300 else /* XXX Perform clean-up after last target build. */ 00301 ba->buildAmount |= cleanFlags; 00302 00303 rpmlog(RPMLOG_DEBUG, _(" target platform: %s\n"), target); 00304 00305 /* Read in configuration for target. */ 00306 if (t != targets) { 00307 rpmFreeMacros(NULL); 00308 rpmFreeRpmrc(); 00309 (void) rpmReadConfigFiles(rcfile, target); 00310 } 00311 rc = buildForTarget(ts, arg, ba); 00312 nbuilds++; 00313 if (rc) 00314 break; 00315 } 00316 00317 exit: 00318 /* Restore original configuration. */ 00319 if (nbuilds > 1) { 00320 t = targets; 00321 if ((te = strchr(t, ',')) == NULL) 00322 te = t + strlen(t); 00323 target = alloca(te-t+1); 00324 strncpy(target, t, (te-t)); 00325 target[te-t] = '\0'; 00326 if (*te != '\0') 00327 te++; 00328 rpmFreeMacros(NULL); 00329 rpmFreeRpmrc(); 00330 (void) rpmReadConfigFiles(rcfile, target); 00331 } 00332 vsflags = rpmtsSetVSFlags(ts, ovsflags); 00333 00334 return rc; 00335 }