rpm
4.5
|
00001 00005 #include "system.h" 00006 00007 #include <rpmcli.h> 00008 #include <rpmbuild.h> 00009 00010 #include "rpmps.h" 00011 #include "rpmte.h" 00012 #include "rpmts.h" 00013 00014 #include "build.h" 00015 #include "debug.h" 00016 00017 /*@access rpmts @*/ /* XXX compared with NULL @*/ 00018 /*@access rpmdb @*/ /* XXX compared with NULL @*/ 00019 /*@access FD_t @*/ /* XXX compared with NULL @*/ 00020 00023 static int checkSpec(rpmts ts, Header h) 00024 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00025 /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/ 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 rpmMessage(RPMMESS_ERROR, _("Failed build dependencies:\n")); 00041 rpmpsPrint(NULL, ps); 00042 rc = 1; 00043 } 00044 ps = rpmpsFree(ps); 00045 00046 /* XXX nuke the added package. */ 00047 rpmtsClean(ts); 00048 00049 return rc; 00050 } 00051 00052 /* 00053 * Kurwa, durni ameryka?ce sobe zawsze my?l?, ?e ca?y ?wiat mówi po 00054 * angielsku... 00055 */ 00056 /* XXX this is still a dumb test but at least it's i18n aware */ 00059 static int isSpecFile(const char * specfile) 00060 /*@globals h_errno, fileSystem, internalState @*/ 00061 /*@modifies fileSystem, internalState @*/ 00062 { 00063 char buf[256]; 00064 const char * s; 00065 FD_t fd; 00066 int count; 00067 int checking; 00068 00069 fd = Fopen(specfile, "r"); 00070 if (fd == NULL || Ferror(fd)) { 00071 rpmError(RPMERR_OPEN, _("Unable to open spec file %s: %s\n"), 00072 specfile, Fstrerror(fd)); 00073 return 0; 00074 } 00075 count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd); 00076 (void) Fclose(fd); 00077 00078 checking = 1; 00079 for (s = buf; count--; s++) { 00080 switch (*s) { 00081 case '\r': 00082 case '\n': 00083 checking = 1; 00084 /*@switchbreak@*/ break; 00085 case ':': 00086 checking = 0; 00087 /*@switchbreak@*/ break; 00088 /*@-boundsread@*/ 00089 default: 00090 if (checking && !(isprint(*s) || isspace(*s))) return 0; 00091 /*@switchbreak@*/ break; 00092 /*@=boundsread@*/ 00093 } 00094 } 00095 return 1; 00096 } 00097 00100 /*@-boundswrite@*/ 00101 static int buildForTarget(rpmts ts, const char * arg, BTA_t ba) 00102 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00103 /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/ 00104 { 00105 const char * passPhrase = ba->passPhrase; 00106 const char * cookie = ba->cookie; 00107 int buildAmount = ba->buildAmount; 00108 const char * specFile; 00109 const char * specURL; 00110 int specut; 00111 char buf[BUFSIZ]; 00112 Spec spec = NULL; 00113 int verify = 1; 00114 int xx; 00115 int rc; 00116 00117 #ifndef DYING 00118 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS); 00119 #endif 00120 00121 /*@-compmempass@*/ /* FIX: static zcmds heartburn */ 00122 if (ba->buildMode == 't') { 00123 FILE *fp; 00124 const char * specDir; 00125 char * tmpSpecFile; 00126 char * cmd, * s; 00127 rpmCompressedMagic res = COMPRESSED_OTHER; 00128 /*@observer@*/ static const char *zcmds[] = 00129 { "cat", "gunzip", "bunzip2", "cat" }; 00130 00131 specDir = rpmGetPath("%{_specdir}", NULL); 00132 00133 tmpSpecFile = (char *) rpmGetPath("%{_specdir}/", "rpm-spec.XXXXXX", NULL); 00134 #if defined(HAVE_MKSTEMP) 00135 (void) close(mkstemp(tmpSpecFile)); 00136 #else 00137 (void) mktemp(tmpSpecFile); 00138 #endif 00139 00140 (void) isCompressed(arg, &res); 00141 00142 cmd = alloca(strlen(arg) + 50 + strlen(tmpSpecFile)); 00143 sprintf(cmd, "%s < %s | tar xOvf - Specfile 2>&1 > %s", 00144 zcmds[res & 0x3], arg, tmpSpecFile); 00145 if (!(fp = popen(cmd, "r"))) { 00146 rpmError(RPMERR_POPEN, _("Failed to open tar pipe: %m\n")); 00147 specDir = _free(specDir); 00148 tmpSpecFile = _free(tmpSpecFile); 00149 return 1; 00150 } 00151 if ((!fgets(buf, sizeof(buf) - 1, fp)) || !strchr(buf, '/')) { 00152 /* Try again */ 00153 (void) pclose(fp); 00154 00155 sprintf(cmd, "%s < %s | tar xOvf - --wildcards \\*.spec 2>&1 > %s", 00156 zcmds[res & 0x3], arg, tmpSpecFile); 00157 if (!(fp = popen(cmd, "r"))) { 00158 rpmError(RPMERR_POPEN, _("Failed to open tar pipe: %m\n")); 00159 specDir = _free(specDir); 00160 tmpSpecFile = _free(tmpSpecFile); 00161 return 1; 00162 } 00163 if (!fgets(buf, sizeof(buf) - 1, fp)) { 00164 /* Give up */ 00165 rpmError(RPMERR_READ, _("Failed to read spec file from %s\n"), 00166 arg); 00167 (void) unlink(tmpSpecFile); 00168 specDir = _free(specDir); 00169 tmpSpecFile = _free(tmpSpecFile); 00170 return 1; 00171 } 00172 } 00173 (void) pclose(fp); 00174 00175 cmd = s = buf; 00176 while (*cmd != '\0') { 00177 if (*cmd == '/') s = cmd + 1; 00178 cmd++; 00179 } 00180 00181 cmd = s; 00182 00183 /* remove trailing \n */ 00184 s = cmd + strlen(cmd) - 1; 00185 *s = '\0'; 00186 00187 specURL = s = alloca(strlen(specDir) + strlen(cmd) + 5); 00188 sprintf(s, "%s/%s", specDir, cmd); 00189 res = rename(tmpSpecFile, s); 00190 specDir = _free(specDir); 00191 00192 if (res) { 00193 rpmError(RPMERR_RENAME, _("Failed to rename %s to %s: %m\n"), 00194 tmpSpecFile, s); 00195 (void) unlink(tmpSpecFile); 00196 tmpSpecFile = _free(tmpSpecFile); 00197 return 1; 00198 } 00199 tmpSpecFile = _free(tmpSpecFile); 00200 00201 /* Make the directory which contains the tarball the source 00202 directory for this run */ 00203 00204 if (*arg != '/') { 00205 if (getcwd(buf, BUFSIZ) == NULL) strcpy(buf, "."); 00206 strcat(buf, "/"); 00207 strcat(buf, arg); 00208 } else 00209 strcpy(buf, arg); 00210 00211 cmd = buf + strlen(buf) - 1; 00212 while (*cmd != '/') cmd--; 00213 *cmd = '\0'; 00214 00215 addMacro(NULL, "_sourcedir", NULL, buf, RMIL_TARBALL); 00216 } else { 00217 specURL = arg; 00218 } 00219 /*@=compmempass@*/ 00220 00221 specut = urlPath(specURL, &specFile); 00222 if (*specFile != '/') { 00223 char *s = alloca(BUFSIZ); 00224 if (getcwd(s, BUFSIZ) == NULL) strcpy(s, "."); 00225 strcat(s, "/"); 00226 strcat(s, arg); 00227 specURL = s; 00228 } 00229 00230 if (specut != URL_IS_DASH) { 00231 struct stat st; 00232 if (Stat(specURL, &st) < 0) { 00233 rpmError(RPMERR_STAT, _("failed to stat %s: %m\n"), specURL); 00234 rc = 1; 00235 goto exit; 00236 } 00237 if (! S_ISREG(st.st_mode)) { 00238 rpmError(RPMERR_NOTREG, _("File %s is not a regular file.\n"), 00239 specURL); 00240 rc = 1; 00241 goto exit; 00242 } 00243 00244 /* Try to verify that the file is actually a specfile */ 00245 if (!isSpecFile(specURL)) { 00246 rpmError(RPMERR_BADSPEC, 00247 _("File %s does not appear to be a specfile.\n"), specURL); 00248 rc = 1; 00249 goto exit; 00250 } 00251 } 00252 00253 /* Parse the spec file */ 00254 #define _anyarch(_f) \ 00255 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0) 00256 if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase, 00257 cookie, _anyarch(buildAmount), ba->force, verify)) 00258 { 00259 rc = 1; 00260 goto exit; 00261 } 00262 #undef _anyarch 00263 if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) { 00264 rc = 1; 00265 goto exit; 00266 } 00267 00268 /* Assemble source header from parsed components */ 00269 xx = initSourceHeader(spec, NULL); 00270 00271 /* Check build prerequisites */ 00272 if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) { 00273 rc = 1; 00274 goto exit; 00275 } 00276 00277 if (buildSpec(ts, spec, buildAmount, ba->noBuild)) { 00278 rc = 1; 00279 goto exit; 00280 } 00281 00282 if (ba->buildMode == 't') 00283 (void) Unlink(specURL); 00284 rc = 0; 00285 00286 exit: 00287 spec = freeSpec(spec); 00288 return rc; 00289 } 00290 /*@=boundswrite@*/ 00291 00292 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile) 00293 { 00294 const char *t, *te; 00295 int rc = 0; 00296 const char * targets = rpmcliTargets; 00297 char *target; 00298 #define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC) 00299 int cleanFlags = ba->buildAmount & buildCleanMask; 00300 rpmVSFlags vsflags, ovsflags; 00301 int nbuilds = 0; 00302 00303 vsflags = rpmExpandNumeric("%{_vsflags_build}"); 00304 if (ba->qva_flags & VERIFY_DIGEST) 00305 vsflags |= _RPMVSF_NODIGESTS; 00306 if (ba->qva_flags & VERIFY_SIGNATURE) 00307 vsflags |= _RPMVSF_NOSIGNATURES; 00308 if (ba->qva_flags & VERIFY_HDRCHK) 00309 vsflags |= RPMVSF_NOHDRCHK; 00310 ovsflags = rpmtsSetVSFlags(ts, vsflags); 00311 00312 if (targets == NULL) { 00313 rc = buildForTarget(ts, arg, ba); 00314 nbuilds++; 00315 goto exit; 00316 } 00317 00318 /* parse up the build operators */ 00319 00320 printf(_("Building target platforms: %s\n"), targets); 00321 00322 ba->buildAmount &= ~buildCleanMask; 00323 for (t = targets; *t != '\0'; t = te) { 00324 /* Parse out next target platform. */ 00325 if ((te = strchr(t, ',')) == NULL) 00326 te = t + strlen(t); 00327 target = alloca(te-t+1); 00328 strncpy(target, t, (te-t)); 00329 target[te-t] = '\0'; 00330 if (*te != '\0') 00331 te++; 00332 else /* XXX Perform clean-up after last target build. */ 00333 ba->buildAmount |= cleanFlags; 00334 00335 rpmMessage(RPMMESS_DEBUG, D_(" target platform: %s\n"), target); 00336 00337 /* Read in configuration for target. */ 00338 if (t != targets) { 00339 rpmFreeMacros(NULL); 00340 rpmFreeRpmrc(); 00341 (void) rpmReadConfigFiles(rcfile, target); 00342 } 00343 rc = buildForTarget(ts, arg, ba); 00344 nbuilds++; 00345 if (rc) 00346 break; 00347 } 00348 00349 exit: 00350 /* Restore original configuration. */ 00351 if (nbuilds > 1) { 00352 t = targets; 00353 if ((te = strchr(t, ',')) == NULL) 00354 te = t + strlen(t); 00355 target = alloca(te-t+1); 00356 strncpy(target, t, (te-t)); 00357 target[te-t] = '\0'; 00358 if (*te != '\0') 00359 te++; 00360 rpmFreeMacros(NULL); 00361 rpmFreeRpmrc(); 00362 (void) rpmReadConfigFiles(rcfile, target); 00363 } 00364 vsflags = rpmtsSetVSFlags(ts, ovsflags); 00365 00366 return rc; 00367 }