rpm 5.2.1
|
00001 00006 #include "system.h" 00007 00008 #include <rpmio_internal.h> /* XXX fdGetFp */ 00009 #include <rpmcb.h> 00010 #define _RPMTAG_INTERNAL 00011 #include <rpmbuild.h> 00012 #include "signature.h" /* XXX rpmTempFile */ 00013 00014 #include "debug.h" 00015 00016 /*@unchecked@*/ 00017 static int _build_debug = 0; 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 00107 FD_t fd; 00108 FD_t xfd; 00109 pid_t pid; 00110 pid_t child; 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 mTemplate = "%{__spec_prep_template}"; 00120 mPost = "%{__spec_prep_post}"; 00121 mCmd = "%{__spec_prep_cmd}"; 00122 break; 00123 case RPMBUILD_BUILD: 00124 name = "%build"; 00125 iob = spec->build; 00126 mTemplate = "%{__spec_build_template}"; 00127 mPost = "%{__spec_build_post}"; 00128 mCmd = "%{__spec_build_cmd}"; 00129 break; 00130 case RPMBUILD_INSTALL: 00131 name = "%install"; 00132 iob = spec->install; 00133 mTemplate = "%{__spec_install_template}"; 00134 mPost = "%{__spec_install_post}"; 00135 mCmd = "%{__spec_install_cmd}"; 00136 break; 00137 case RPMBUILD_CHECK: 00138 name = "%check"; 00139 iob = spec->check; 00140 mTemplate = "%{__spec_check_template}"; 00141 mPost = "%{__spec_check_post}"; 00142 mCmd = "%{__spec_check_cmd}"; 00143 break; 00144 case RPMBUILD_CLEAN: 00145 name = "%clean"; 00146 iob = spec->clean; 00147 mTemplate = "%{__spec_clean_template}"; 00148 mPost = "%{__spec_clean_post}"; 00149 mCmd = "%{__spec_clean_cmd}"; 00150 break; 00151 case RPMBUILD_RMBUILD: 00152 name = "--clean"; 00153 mTemplate = "%{__spec_clean_template}"; 00154 mPost = "%{__spec_clean_post}"; 00155 mCmd = "%{__spec_clean_cmd}"; 00156 break; 00157 /* support "%track" script/section */ 00158 case RPMBUILD_TRACK: 00159 name = "%track"; 00160 iob = NULL; 00161 if (spec->foo) 00162 for (i = 0; i < spec->nfoo; i++) { 00163 if (spec->foo[i].str == NULL || spec->foo[i].iob == NULL) 00164 continue; 00165 if (xstrcasecmp(spec->foo[i].str, "track")) 00166 continue; 00167 iob = spec->foo[i].iob; 00168 /*@loopbreak@*/ break; 00169 } 00170 mTemplate = "%{__spec_track_template}"; 00171 mPost = "%{__spec_track_post}"; 00172 mCmd = "%{__spec_track_cmd}"; 00173 break; 00174 case RPMBUILD_STRINGBUF: 00175 default: 00176 mTemplate = "%{___build_template}"; 00177 mPost = "%{___build_post}"; 00178 mCmd = "%{___build_cmd}"; 00179 break; 00180 } 00181 if (name == NULL) /* XXX shouldn't happen */ 00182 name = "???"; 00183 00184 if ((what != RPMBUILD_RMBUILD) && iob == NULL) { 00185 rc = RPMRC_OK; 00186 goto exit; 00187 } 00188 00189 if (rpmTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) { 00190 rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n")); 00191 rc = RPMRC_FAIL; 00192 goto exit; 00193 } 00194 00195 if (fdGetFp(fd) == NULL) 00196 xfd = Fdopen(fd, "w.fpio"); 00197 else 00198 xfd = fd; 00199 00200 /*@-type@*/ /* FIX: cast? */ 00201 if ((fp = fdGetFp(xfd)) == NULL) { 00202 rc = RPMRC_FAIL; 00203 goto exit; 00204 } 00205 /*@=type@*/ 00206 00207 (void) urlPath(rootURL, &rootDir); 00208 if (*rootDir == '\0') rootDir = "/"; 00209 00210 (void) urlPath(scriptName, &buildScript); 00211 00212 buildTemplate = rpmExpand(mTemplate, NULL); 00213 buildPost = rpmExpand(mPost, NULL); 00214 00215 (void) fputs(buildTemplate, fp); 00216 00217 /* support "%track" script/section */ 00218 if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir && what != RPMBUILD_TRACK) 00219 fprintf(fp, "cd '%s'\n", spec->buildSubdir); 00220 00221 if (what == RPMBUILD_RMBUILD) { 00222 if (spec->buildSubdir) 00223 fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir); 00224 } else if (iob != NULL) 00225 fprintf(fp, "%s", rpmiobStr(iob)); 00226 00227 (void) fputs(buildPost, fp); 00228 00229 (void) Fclose(xfd); 00230 00231 if (test) { 00232 rc = RPMRC_OK; 00233 goto exit; 00234 } 00235 00236 if (_build_debug) 00237 fprintf(stderr, "*** rootURL %s buildDirURL %s\n", rootURL, buildDirURL); 00238 if (buildDirURL && buildDirURL[0] != '/' && 00239 (urlSplit(buildDirURL, &u) != 0)) { 00240 rc = RPMRC_FAIL; 00241 goto exit; 00242 } 00243 if (u != NULL) { 00244 switch (u->urltype) { 00245 case URL_IS_HTTPS: 00246 case URL_IS_HTTP: 00247 case URL_IS_FTP: 00248 if (_build_debug) 00249 fprintf(stderr, "*** addMacros\n"); 00250 addMacro(spec->macros, "_remsh", NULL, "%{__remsh}", RMIL_SPEC); 00251 addMacro(spec->macros, "_remhost", NULL, u->host, RMIL_SPEC); 00252 if (strcmp(rootDir, "/")) 00253 addMacro(spec->macros, "_remroot", NULL, rootDir, RMIL_SPEC); 00254 break; 00255 case URL_IS_UNKNOWN: 00256 case URL_IS_DASH: 00257 case URL_IS_PATH: 00258 case URL_IS_HKP: 00259 default: 00260 break; 00261 } 00262 } 00263 00264 buildCmd = rpmExpand(mCmd, " ", buildScript, NULL); 00265 (void) poptParseArgvString(buildCmd, &argc, &argv); 00266 00267 if (what != RPMBUILD_TRACK) /* support "%track" script/section */ 00268 rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd); 00269 if (!(child = fork())) { 00270 00271 /*@-mods@*/ 00272 errno = 0; 00273 /*@=mods@*/ 00274 (void) execvp(argv[0], (char *const *)argv); 00275 00276 rpmlog(RPMLOG_ERR, _("Exec of %s failed (%s): %s\n"), 00277 scriptName, name, strerror(errno)); 00278 00279 _exit(-1); 00280 } 00281 00282 pid = waitpid(child, &status, 0); 00283 00284 if (!WIFEXITED(status) || WEXITSTATUS(status)) { 00285 rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"), 00286 scriptName, name); 00287 rc = RPMRC_FAIL; 00288 } else 00289 rc = RPMRC_OK; 00290 00291 exit: 00292 if (scriptName) { 00293 #if defined(RPM_VENDOR_OPENPKG) /* always-remove-tempfiles */ 00294 /* Unconditionally remove temporary files ("rpm-tmp.XXXXX") which 00295 were generated for the executed scripts. In OpenPKG we run the 00296 scripts in debug mode ("set -x") anyway, so we never need to 00297 see the whole generated script -- not even if it breaks. Instead 00298 we would just have temporary files staying around forever. */ 00299 #else 00300 if (rc == RPMRC_OK) 00301 #endif 00302 (void) Unlink(scriptName); 00303 scriptName = _free(scriptName); 00304 } 00305 if (u != NULL) { 00306 switch (u->urltype) { 00307 case URL_IS_HTTPS: 00308 case URL_IS_HTTP: 00309 case URL_IS_FTP: 00310 if (_build_debug) 00311 fprintf(stderr, "*** delMacros\n"); 00312 delMacro(spec->macros, "_remsh"); 00313 delMacro(spec->macros, "_remhost"); 00314 if (strcmp(rootDir, "/")) 00315 delMacro(spec->macros, "_remroot"); 00316 break; 00317 case URL_IS_UNKNOWN: 00318 case URL_IS_DASH: 00319 case URL_IS_PATH: 00320 case URL_IS_HKP: 00321 default: 00322 break; 00323 } 00324 } 00325 argv = _free(argv); 00326 buildCmd = _free(buildCmd); 00327 buildTemplate = _free(buildTemplate); 00328 buildPost = _free(buildPost); 00329 buildDirURL = _free(buildDirURL); 00330 00331 return rc; 00332 } 00333 00334 rpmRC buildSpec(rpmts ts, Spec spec, int what, int test) 00335 { 00336 rpmRC rc = RPMRC_OK; 00337 00338 if (!spec->recursing && spec->BACount) { 00339 int x; 00340 /* When iterating over BANames, do the source */ 00341 /* packaging on the first run, and skip RMSOURCE altogether */ 00342 if (spec->BASpecs != NULL) 00343 for (x = 0; x < spec->BACount; x++) { 00344 if ((rc = buildSpec(ts, spec->BASpecs[x], 00345 (what & ~RPMBUILD_RMSOURCE) | 00346 (x ? 0 : (what & RPMBUILD_PACKAGESOURCE)), 00347 test))) { 00348 goto exit; 00349 } 00350 } 00351 } else { 00352 /* support "%track" script/section */ 00353 if ((what & RPMBUILD_TRACK) && 00354 (rc = doScript(spec, RPMBUILD_TRACK, NULL, NULL, test))) 00355 goto exit; 00356 00357 if ((what & RPMBUILD_PREP) && 00358 (rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test))) 00359 goto exit; 00360 00361 if ((what & RPMBUILD_BUILD) && 00362 (rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test))) 00363 goto exit; 00364 00365 if ((what & RPMBUILD_INSTALL) && 00366 (rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test))) 00367 goto exit; 00368 00369 if ((what & RPMBUILD_CHECK) && 00370 (rc = doScript(spec, RPMBUILD_CHECK, NULL, NULL, test))) 00371 goto exit; 00372 00373 if ((what & RPMBUILD_PACKAGESOURCE) && 00374 (rc = processSourceFiles(spec))) 00375 goto exit; 00376 00377 if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) || 00378 (what & RPMBUILD_FILECHECK)) && 00379 (rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL, test))) 00380 goto exit; 00381 00382 if (((what & RPMBUILD_PACKAGESOURCE) && !test) && 00383 (rc = packageSources(spec))) 00384 return rc; 00385 00386 if (((what & RPMBUILD_PACKAGEBINARY) && !test) && 00387 (rc = packageBinaries(spec))) 00388 goto exit; 00389 00390 if ((what & RPMBUILD_CLEAN) && 00391 (rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test))) 00392 goto exit; 00393 00394 if ((what & RPMBUILD_RMBUILD) && 00395 (rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test))) 00396 goto exit; 00397 } 00398 00399 if (what & RPMBUILD_RMSOURCE) 00400 doRmSource(spec); 00401 00402 if (what & RPMBUILD_RMSPEC) 00403 (void) Unlink(spec->specFile); 00404 00405 #if defined(RPM_VENDOR_OPENPKG) /* auto-remove-source-directories */ 00406 /* In OpenPKG we use per-package %{_sourcedir} and %{_specdir} 00407 definitions (macros have trailing ".../%{name}"). On removal of 00408 source(s) and .spec file, this per-package directory would be kept 00409 (usually <prefix>/RPM/SRC/<name>/), because RPM does not know about 00410 this OpenPKG convention. So, let RPM try(!) to remove the two 00411 directories (if they are empty) and just ignore removal failures 00412 (if they are still not empty). */ 00413 if (what & RPMBUILD_RMSOURCE) { 00414 const char *pn; 00415 pn = rpmGetPath("%{_sourcedir}", NULL); 00416 Rmdir(pn); /* ignore error, it is ok if it fails (usually with ENOTEMPTY) */ 00417 pn = _free(pn); 00418 } 00419 if (what & RPMBUILD_RMSPEC) { 00420 const char *pn; 00421 pn = rpmGetPath("%{_specdir}", NULL); 00422 Rmdir(pn); /* ignore error, it is ok if it fails (usually with ENOTEMPTY) */ 00423 pn = _free(pn); 00424 } 00425 #endif 00426 00427 exit: 00428 if (rc != RPMRC_OK && rpmlogGetNrecs() > 0) { 00429 rpmlog(RPMLOG_NOTICE, _("\n\nRPM build errors:\n")); 00430 rpmlogPrint(NULL); 00431 } 00432 00433 return rc; 00434 }