rpm 5.3.12
|
00001 00006 #include "system.h" 00007 00008 #define _RPMBC_INTERNAL 00009 #include <rpmio_internal.h> /* XXX fdGetFp */ 00010 #include <rpmcb.h> 00011 #include <rpmsq.h> 00012 00013 #define _RPMTAG_INTERNAL 00014 #include <rpmbuild.h> 00015 #include "signature.h" /* XXX rpmTempFile */ 00016 00017 #include "debug.h" 00018 00021 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ 00022 const char * getSourceDir(rpmfileAttrs attr, const char *filename) 00023 #else 00024 const char * getSourceDir(rpmfileAttrs attr) 00025 #endif 00026 { 00027 const char * dir = NULL; 00028 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ 00029 const char *fn; 00030 00031 /* support splitted source directories, i.e., source files which 00032 are alternatively placed into the .spec directory and picked 00033 up from there, too. */ 00034 if (attr & (RPMFILE_SOURCE|RPMFILE_PATCH|RPMFILE_ICON) && filename != NULL) 00035 { 00036 fn = rpmGetPath("%{_specdir}/", filename, NULL); 00037 if (access(fn, F_OK) == 0) 00038 dir = "%{_specdir}/"; 00039 fn = _free(fn); 00040 } 00041 if (dir != NULL) { 00042 } else 00043 #endif 00044 if (attr & RPMFILE_SOURCE) 00045 dir = "%{_sourcedir}/"; 00046 else if (attr & RPMFILE_PATCH) 00047 dir = "%{_patchdir}/"; 00048 else if (attr & RPMFILE_ICON) 00049 dir = "%{_icondir}/"; 00050 00051 return dir; 00052 } 00053 00054 /*@access urlinfo @*/ /* XXX compared with NULL */ 00055 /*@access FD_t @*/ 00056 00059 static void doRmSource(Spec spec) 00060 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00061 /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/ 00062 { 00063 struct Source *sp; 00064 int rc; 00065 00066 #if 0 00067 rc = Unlink(spec->specFile); 00068 #endif 00069 00070 for (sp = spec->sources; sp != NULL; sp = sp->next) { 00071 const char *dn, *fn; 00072 if (sp->flags & RPMFILE_GHOST) 00073 continue; 00074 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ 00075 if (! (dn = getSourceDir(sp->flags, sp->source))) 00076 #else 00077 if (! (dn = getSourceDir(sp->flags))) 00078 #endif 00079 continue; 00080 fn = rpmGenPath(NULL, dn, sp->source); 00081 rc = Unlink(fn); 00082 fn = _free(fn); 00083 } 00084 } 00085 00086 /* 00087 * @todo Single use by %%doc in files.c prevents static. 00088 */ 00089 rpmRC doScript(Spec spec, int what, const char *name, rpmiob iob, int test) 00090 { 00091 const char * rootURL = spec->rootURL; 00092 const char * rootDir; 00093 const char * scriptName = NULL; 00094 const char * buildDirURL = rpmGenPath(rootURL, "%{_builddir}", ""); 00095 const char * buildScript; 00096 const char * buildCmd = NULL; 00097 const char * buildTemplate = NULL; 00098 const char * buildPost = NULL; 00099 const char * mTemplate = NULL; 00100 const char * mCmd = NULL; 00101 const char * mPost = NULL; 00102 int argc = 0; 00103 const char **argv = NULL; 00104 FILE * fp = NULL; 00105 urlinfo u = NULL; 00106 rpmop op = NULL; 00107 int ix = -1; 00108 00109 FD_t fd; 00110 FD_t xfd; 00111 int status; 00112 rpmRC rc; 00113 size_t i; 00114 00115 switch (what) { 00116 case RPMBUILD_PREP: 00117 name = "%prep"; 00118 iob = spec->prep; 00119 op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); 00120 ix = RPMSCRIPT_PREP; 00121 mTemplate = "%{__spec_prep_template}"; 00122 mPost = "%{__spec_prep_post}"; 00123 mCmd = "%{__spec_prep_cmd}"; 00124 break; 00125 case RPMBUILD_BUILD: 00126 name = "%build"; 00127 iob = spec->build; 00128 op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); 00129 ix = RPMSCRIPT_BUILD; 00130 mTemplate = "%{__spec_build_template}"; 00131 mPost = "%{__spec_build_post}"; 00132 mCmd = "%{__spec_build_cmd}"; 00133 break; 00134 case RPMBUILD_INSTALL: 00135 name = "%install"; 00136 iob = spec->install; 00137 op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); 00138 ix = RPMSCRIPT_INSTALL; 00139 mTemplate = "%{__spec_install_template}"; 00140 mPost = "%{__spec_install_post}"; 00141 mCmd = "%{__spec_install_cmd}"; 00142 break; 00143 case RPMBUILD_CHECK: 00144 name = "%check"; 00145 iob = spec->check; 00146 op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); 00147 ix = RPMSCRIPT_CHECK; 00148 mTemplate = "%{__spec_check_template}"; 00149 mPost = "%{__spec_check_post}"; 00150 mCmd = "%{__spec_check_cmd}"; 00151 break; 00152 case RPMBUILD_CLEAN: 00153 name = "%clean"; 00154 iob = spec->clean; 00155 mTemplate = "%{__spec_clean_template}"; 00156 mPost = "%{__spec_clean_post}"; 00157 mCmd = "%{__spec_clean_cmd}"; 00158 break; 00159 case RPMBUILD_RMBUILD: 00160 name = "--clean"; 00161 mTemplate = "%{__spec_clean_template}"; 00162 mPost = "%{__spec_clean_post}"; 00163 mCmd = "%{__spec_clean_cmd}"; 00164 break; 00165 /* support "%track" script/section */ 00166 case RPMBUILD_TRACK: 00167 name = "%track"; 00168 iob = NULL; 00169 if (spec->foo) 00170 for (i = 0; i < spec->nfoo; i++) { 00171 if (spec->foo[i].str == NULL || spec->foo[i].iob == NULL) 00172 continue; 00173 if (xstrcasecmp(spec->foo[i].str, "track")) 00174 continue; 00175 iob = spec->foo[i].iob; 00176 /*@loopbreak@*/ break; 00177 } 00178 mTemplate = "%{__spec_track_template}"; 00179 mPost = "%{__spec_track_post}"; 00180 mCmd = "%{__spec_track_cmd}"; 00181 break; 00182 case RPMBUILD_STRINGBUF: 00183 default: 00184 mTemplate = "%{___build_template}"; 00185 mPost = "%{___build_post}"; 00186 mCmd = "%{___build_cmd}"; 00187 break; 00188 } 00189 00190 assert(name != NULL); 00191 00192 if ((what != RPMBUILD_RMBUILD) && iob == NULL) { 00193 rc = RPMRC_OK; 00194 goto exit; 00195 } 00196 00197 if (rpmTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) { 00198 rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n")); 00199 rc = RPMRC_FAIL; 00200 goto exit; 00201 } 00202 00203 if (fdGetFp(fd) == NULL) 00204 xfd = Fdopen(fd, "w.fpio"); 00205 else 00206 xfd = fd; 00207 00208 /*@-type@*/ /* FIX: cast? */ 00209 if ((fp = fdGetFp(xfd)) == NULL) { 00210 rc = RPMRC_FAIL; 00211 goto exit; 00212 } 00213 /*@=type@*/ 00214 00215 (void) urlPath(rootURL, &rootDir); 00216 if (*rootDir == '\0') rootDir = "/"; 00217 00218 (void) urlPath(scriptName, &buildScript); 00219 00220 buildTemplate = rpmExpand(mTemplate, NULL); 00221 buildPost = rpmExpand(mPost, NULL); 00222 00223 (void) fputs(buildTemplate, fp); 00224 00225 /* support "%track" script/section */ 00226 if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir && what != RPMBUILD_TRACK) 00227 fprintf(fp, "cd '%s'\n", spec->buildSubdir); 00228 00229 if (what == RPMBUILD_RMBUILD) { 00230 if (spec->buildSubdir) 00231 fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir); 00232 } else if (iob != NULL) 00233 fprintf(fp, "%s", rpmiobStr(iob)); 00234 00235 (void) fputs(buildPost, fp); 00236 00237 (void) Fclose(xfd); 00238 00239 if (test) { 00240 rc = RPMRC_OK; 00241 goto exit; 00242 } 00243 00244 if (buildDirURL && buildDirURL[0] != '/' && 00245 (urlSplit(buildDirURL, &u) != 0)) { 00246 rc = RPMRC_FAIL; 00247 goto exit; 00248 } 00249 00250 switch (urlType(u)) { 00251 case URL_IS_HTTPS: 00252 case URL_IS_HTTP: 00253 case URL_IS_FTP: 00254 addMacro(spec->macros, "_remsh", NULL, "%{__remsh}", RMIL_SPEC); 00255 addMacro(spec->macros, "_remhost", NULL, u->host, RMIL_SPEC); 00256 if (strcmp(rootDir, "/")) 00257 addMacro(spec->macros, "_remroot", NULL, rootDir, RMIL_SPEC); 00258 break; 00259 case URL_IS_UNKNOWN: 00260 case URL_IS_DASH: 00261 case URL_IS_PATH: 00262 case URL_IS_HKP: 00263 default: 00264 break; 00265 } 00266 00267 buildCmd = rpmExpand(mCmd, " ", buildScript, NULL); 00268 (void) poptParseArgvString(buildCmd, &argc, &argv); 00269 00270 if (what != RPMBUILD_TRACK) /* support "%track" script/section */ 00271 rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd); 00272 00273 /* Run the script with a stopwatch. */ 00274 if (op != NULL) 00275 (void) rpmswEnter(op, 0); 00276 00277 status = rpmsqExecve(argv); 00278 if (ix >= 0 && ix < RPMSCRIPT_MAX) 00279 spec->sstates[ix] = 00280 (RPMSCRIPT_STATE_EXEC | RPMSCRIPT_STATE_REAPED) | (status & 0xffff); 00281 00282 if (!WIFEXITED(status) || WEXITSTATUS(status)) { 00283 rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"), 00284 scriptName, name); 00285 rc = RPMRC_FAIL; 00286 } else 00287 rc = RPMRC_OK; 00288 00289 if (op != NULL) { 00290 static unsigned int scale = 1000; 00291 (void) rpmswExit(op, 0); 00292 if (ix >= 0 && ix < RPMSCRIPT_MAX) 00293 spec->smetrics[ix] += op->usecs / scale; 00294 } 00295 00296 exit: 00297 if (scriptName) { 00298 #if defined(RPM_VENDOR_OPENPKG) /* always-remove-tempfiles */ 00299 /* Unconditionally remove temporary files ("rpm-tmp.XXXXX") which 00300 were generated for the executed scripts. In OpenPKG we run the 00301 scripts in debug mode ("set -x") anyway, so we never need to 00302 see the whole generated script -- not even if it breaks. Instead 00303 we would just have temporary files staying around forever. */ 00304 #else 00305 if (rc == RPMRC_OK) 00306 #endif 00307 (void) Unlink(scriptName); 00308 scriptName = _free(scriptName); 00309 } 00310 00311 switch (urlType(u)) { 00312 case URL_IS_HTTPS: 00313 case URL_IS_HTTP: 00314 case URL_IS_FTP: 00315 delMacro(spec->macros, "_remsh"); 00316 delMacro(spec->macros, "_remhost"); 00317 if (strcmp(rootDir, "/")) 00318 delMacro(spec->macros, "_remroot"); 00319 break; 00320 case URL_IS_UNKNOWN: 00321 case URL_IS_DASH: 00322 case URL_IS_PATH: 00323 case URL_IS_HKP: 00324 default: 00325 break; 00326 } 00327 00328 argv = _free(argv); 00329 buildCmd = _free(buildCmd); 00330 buildTemplate = _free(buildTemplate); 00331 buildPost = _free(buildPost); 00332 buildDirURL = _free(buildDirURL); 00333 return rc; 00334 } 00335 00336 rpmRC buildSpec(rpmts ts, Spec spec, int what, int test) 00337 { 00338 rpmRC rc = RPMRC_OK; 00339 00340 /* Generate a keypair lazily. */ 00341 if (spec->dig == NULL) 00342 spec->dig = pgpDigNew(RPMVSF_DEFAULT, PGPPUBKEYALGO_DSA); 00343 00344 if (!spec->recursing && spec->BACount) { 00345 int x; 00346 /* When iterating over BANames, do the source */ 00347 /* packaging on the first run, and skip RMSOURCE altogether */ 00348 if (spec->BASpecs != NULL) 00349 for (x = 0; x < spec->BACount; x++) { 00350 if ((rc = buildSpec(ts, spec->BASpecs[x], 00351 (what & ~RPMBUILD_RMSOURCE) | 00352 (x ? 0 : (what & RPMBUILD_PACKAGESOURCE)), 00353 test))) { 00354 goto exit; 00355 } 00356 } 00357 } else { 00358 /* support "%track" script/section */ 00359 if ((what & RPMBUILD_TRACK) && 00360 (rc = doScript(spec, RPMBUILD_TRACK, NULL, NULL, test))) 00361 goto exit; 00362 00363 if ((what & RPMBUILD_PREP) && 00364 (rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test))) 00365 goto exit; 00366 00367 if ((what & RPMBUILD_BUILD) && 00368 (rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test))) 00369 goto exit; 00370 00371 if ((what & RPMBUILD_INSTALL) && 00372 (rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test))) 00373 goto exit; 00374 00375 if ((what & RPMBUILD_CHECK) && 00376 (rc = doScript(spec, RPMBUILD_CHECK, NULL, NULL, test))) 00377 goto exit; 00378 00379 if ((what & RPMBUILD_PACKAGESOURCE) && 00380 (rc = processSourceFiles(spec))) 00381 goto exit; 00382 00383 if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) || 00384 (what & RPMBUILD_FILECHECK)) && 00385 (rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL, test))) 00386 goto exit; 00387 00388 if (((what & RPMBUILD_PACKAGESOURCE) && !test) && 00389 (rc = packageSources(spec))) 00390 return rc; 00391 00392 if (((what & RPMBUILD_PACKAGEBINARY) && !test) && 00393 (rc = packageBinaries(spec))) 00394 goto exit; 00395 00396 if ((what & RPMBUILD_CLEAN) && 00397 (rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test))) 00398 goto exit; 00399 00400 if ((what & RPMBUILD_RMBUILD) && 00401 (rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test))) 00402 goto exit; 00403 } 00404 00405 if (what & RPMBUILD_RMSOURCE) 00406 doRmSource(spec); 00407 00408 if (what & RPMBUILD_RMSPEC) 00409 (void) Unlink(spec->specFile); 00410 00411 #if defined(RPM_VENDOR_OPENPKG) /* auto-remove-source-directories */ 00412 /* In OpenPKG we use per-package %{_sourcedir} and %{_specdir} 00413 definitions (macros have trailing ".../%{name}"). On removal of 00414 source(s) and .spec file, this per-package directory would be kept 00415 (usually <prefix>/RPM/SRC/<name>/), because RPM does not know about 00416 this OpenPKG convention. So, let RPM try(!) to remove the two 00417 directories (if they are empty) and just ignore removal failures 00418 (if they are still not empty). */ 00419 if (what & RPMBUILD_RMSOURCE) { 00420 const char *pn; 00421 pn = rpmGetPath("%{_sourcedir}", NULL); 00422 Rmdir(pn); /* ignore error, it is ok if it fails (usually with ENOTEMPTY) */ 00423 pn = _free(pn); 00424 } 00425 if (what & RPMBUILD_RMSPEC) { 00426 const char *pn; 00427 pn = rpmGetPath("%{_specdir}", NULL); 00428 Rmdir(pn); /* ignore error, it is ok if it fails (usually with ENOTEMPTY) */ 00429 pn = _free(pn); 00430 } 00431 #endif 00432 00433 exit: 00434 if (rc != RPMRC_OK && rpmlogGetNrecs() > 0) { 00435 rpmlog(RPMLOG_NOTICE, _("\n\nRPM build errors:\n")); 00436 rpmlogPrint(NULL); 00437 } 00438 00439 return rc; 00440 }