rpm 5.3.12
|
00001 00006 #include "system.h" 00007 00008 #include <rpmio.h> 00009 #include <rpmiotypes.h> 00010 #include <argv.h> 00011 #include <rpmcb.h> 00012 #include <rpmurl.h> 00013 #ifdef NOTYET 00014 #include <rpmmg.h> 00015 #endif 00016 00017 #include <rpmbuild.h> 00018 00019 #include "misc.h" /* XXX rpmMkdirPath */ 00020 #include "debug.h" 00021 00022 /* These have to be global to make up for stupid compilers */ 00023 /*@unchecked@*/ 00024 static int leaveDirs, skipDefaultAction; 00025 /*@unchecked@*/ 00026 static int createDir, quietly; 00027 /*@unchecked@*/ /*@observer@*/ /*@null@*/ 00028 static const char * dirName = NULL; 00029 /*@unchecked@*/ /*@observer@*/ 00030 static struct poptOption optionsTable[] = { 00031 { NULL, 'a', POPT_ARG_STRING, NULL, 'a', NULL, NULL}, 00032 { NULL, 'b', POPT_ARG_STRING, NULL, 'b', NULL, NULL}, 00033 { NULL, 'c', 0, &createDir, 0, NULL, NULL}, 00034 { NULL, 'D', 0, &leaveDirs, 0, NULL, NULL}, 00035 { NULL, 'n', POPT_ARG_STRING, &dirName, 0, NULL, NULL}, 00036 { NULL, 'T', 0, &skipDefaultAction, 0, NULL, NULL}, 00037 { NULL, 'q', 0, &quietly, 0, NULL, NULL}, 00038 { 0, 0, 0, 0, 0, NULL, NULL} 00039 }; 00040 00046 static rpmRC checkOwners(const char * urlfn) 00047 /*@globals h_errno, fileSystem, internalState @*/ 00048 /*@modifies fileSystem, internalState @*/ 00049 { 00050 struct stat sb; 00051 00052 if (Lstat(urlfn, &sb)) { 00053 rpmlog(RPMLOG_ERR, _("Bad source: %s: %s\n"), 00054 urlfn, strerror(errno)); 00055 return RPMRC_FAIL; 00056 } 00057 if (!getUname(sb.st_uid) || !getGname(sb.st_gid)) { 00058 rpmlog(RPMLOG_ERR, _("Bad owner/group: %s\n"), urlfn); 00059 return RPMRC_FAIL; 00060 } 00061 00062 return RPMRC_OK; 00063 } 00064 00065 #ifndef DYING 00066 00078 /*@observer@*/ 00079 static char *doPatch(Spec spec, rpmuint32_t c, int strip, const char *db, 00080 int reverse, int removeEmpties, int fuzz, const char *subdir) 00081 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00082 /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/ 00083 { 00084 const char *fn, *Lurlfn; 00085 static char buf[BUFSIZ]; 00086 char args[BUFSIZ], *t = args; 00087 struct Source *sp; 00088 rpmCompressedMagic compressed = COMPRESSED_NOT; 00089 int urltype; 00090 const char *patch, *flags; 00091 00092 *t = '\0'; 00093 if (db) 00094 t = stpcpy( stpcpy(t, "-b --suffix "), db); 00095 #if defined(RPM_VENDOR_OPENPKG) /* always-backup-on-patching */ 00096 /* always create backup files in OpenPKG */ 00097 else 00098 t = stpcpy(t, "-b --suffix .orig "); 00099 #endif 00100 if (subdir) 00101 t = stpcpy( stpcpy(t, "-d "), subdir); 00102 if (fuzz >= 0) { 00103 t = stpcpy(t, "-F "); 00104 sprintf(t, "%10.10d", fuzz); 00105 t += strlen(t); 00106 } 00107 if (reverse) 00108 t = stpcpy(t, " -R"); 00109 if (removeEmpties) 00110 t = stpcpy(t, " -E"); 00111 00112 for (sp = spec->sources; sp != NULL; sp = sp->next) { 00113 if ((sp->flags & RPMFILE_PATCH) && (sp->num == c)) 00114 break; 00115 } 00116 if (sp == NULL) { 00117 rpmlog(RPMLOG_ERR, _("No patch number %d\n"), c); 00118 return NULL; 00119 } 00120 00121 Lurlfn = rpmGenPath(NULL, "%{_patchdir}/", sp->source); 00122 00123 /* XXX On non-build parse's, file cannot be stat'd or read */ 00124 if (!spec->force && (isCompressed(Lurlfn, &compressed) || checkOwners(Lurlfn))) { 00125 Lurlfn = _free(Lurlfn); 00126 return NULL; 00127 } 00128 00129 fn = NULL; 00130 urltype = urlPath(Lurlfn, &fn); 00131 switch (urltype) { 00132 case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */ 00133 case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ 00134 case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ 00135 case URL_IS_HKP: /* XXX WRONG WRONG WRONG */ 00136 case URL_IS_PATH: 00137 case URL_IS_UNKNOWN: 00138 break; 00139 case URL_IS_DASH: 00140 Lurlfn = _free(Lurlfn); 00141 return NULL; 00142 /*@notreached@*/ break; 00143 } 00144 00145 patch = rpmGetPath("%{__patch}", NULL); 00146 if (strcmp(patch, "%{__patch}") == 0) 00147 patch = xstrdup("patch"); 00148 00149 flags = rpmExpand("%{?_default_patch_flags}%{!?_default_patch_flags:-s}", NULL); 00150 00151 if (compressed) { 00152 const char *zipper; 00153 00154 switch (compressed) { 00155 default: 00156 case COMPRESSED_NOT: /* XXX can't happen */ 00157 case COMPRESSED_OTHER: 00158 case COMPRESSED_ZIP: /* XXX wrong */ 00159 zipper = "%{__gzip}"; 00160 break; 00161 case COMPRESSED_BZIP2: 00162 zipper = "%{__bzip2}"; 00163 break; 00164 case COMPRESSED_LZOP: 00165 zipper = "%{__lzop}"; 00166 break; 00167 case COMPRESSED_LZMA: 00168 zipper = "%{__lzma}"; 00169 break; 00170 case COMPRESSED_XZ: 00171 zipper = "%{__xz}"; 00172 break; 00173 } 00174 zipper = rpmGetPath(zipper, NULL); 00175 00176 sprintf(buf, 00177 "echo \"Patch #%d (%s):\"\n" 00178 "%s -d < '%s' | %s -p%d %s %s\n" 00179 "STATUS=$?\n" 00180 "if [ $STATUS -ne 0 ]; then\n" 00181 " exit $STATUS\n" 00182 "fi", 00183 c, 00184 /*@-moduncon@*/ 00185 (const char *) basename((char *)fn), 00186 /*@=moduncon@*/ 00187 zipper, 00188 fn, patch, strip, args, flags); 00189 zipper = _free(zipper); 00190 } else { 00191 sprintf(buf, 00192 "echo \"Patch #%d (%s):\"\n" 00193 "%s -p%d %s %s < '%s'", c, 00194 /*@-moduncon@*/ 00195 (const char *) basename((char *)fn), 00196 /*@=moduncon@*/ 00197 patch, strip, args, flags, fn); 00198 } 00199 00200 patch = _free(patch); 00201 flags = _free(flags); 00202 Lurlfn = _free(Lurlfn); 00203 return buf; 00204 } 00205 #endif 00206 00214 /*@observer@*/ 00215 static const char *doUntar(Spec spec, rpmuint32_t c, int quietly) 00216 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00217 /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/ 00218 { 00219 const char *fn, *Lurlfn; 00220 static char buf[BUFSIZ]; 00221 char taropts[8]; 00222 char *t = NULL; 00223 struct Source *sp; 00224 rpmCompressedMagic compressed = COMPRESSED_NOT; 00225 int urltype; 00226 const char *tar; 00227 int rubygem = 0; 00228 00229 for (sp = spec->sources; sp != NULL; sp = sp->next) { 00230 if ((sp->flags & RPMFILE_SOURCE) && (sp->num == c)) { 00231 break; 00232 } 00233 } 00234 if (sp == NULL) { 00235 rpmlog(RPMLOG_ERR, _("No source number %d\n"), c); 00236 return NULL; 00237 } 00238 00239 t = strrchr(sp->source, '.'); 00240 if(t && !strcasecmp(t, ".gem")) 00241 rubygem = 1; 00242 00243 t = stpcpy(taropts, "-x"); 00244 /*@-internalglobs@*/ /* FIX: shrug */ 00245 if(rpmIsVerbose() && !quietly) 00246 t = stpcpy(t, "vv"); 00247 if(rubygem) 00248 t = stpcpy(t, "m"); 00249 00250 t = stpcpy(t, "f"); 00251 /*@=internalglobs@*/ 00252 00253 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ 00254 Lurlfn = rpmGenPath(NULL, getSourceDir(sp->flags, sp->source), sp->source); 00255 #else 00256 Lurlfn = rpmGenPath(NULL, getSourceDir(sp->flags), sp->source); 00257 #endif 00258 00259 /* XXX On non-build parse's, file cannot be stat'd or read */ 00260 if (!spec->force && (isCompressed(Lurlfn, &compressed) || checkOwners(Lurlfn))) { 00261 Lurlfn = _free(Lurlfn); 00262 return NULL; 00263 } 00264 00265 fn = NULL; 00266 urltype = urlPath(Lurlfn, &fn); 00267 switch (urltype) { 00268 case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */ 00269 case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ 00270 case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ 00271 case URL_IS_HKP: /* XXX WRONG WRONG WRONG */ 00272 case URL_IS_PATH: 00273 case URL_IS_UNKNOWN: 00274 break; 00275 case URL_IS_DASH: 00276 Lurlfn = _free(Lurlfn); 00277 return NULL; 00278 /*@notreached@*/ break; 00279 } 00280 #ifdef NOTYET 00281 { rpmmg mg; 00282 00283 _rpmmg_debug = 1; 00284 mg = rpmmgNew(NULL, 0); 00285 t = (char *) rpmmgFile(mg, fn); 00286 mg = rpmmgFree(mg); 00287 fprintf(stderr, "==> %s: %s\n", fn, t); 00288 t = _free(t); 00289 _rpmmg_debug = 0; 00290 } 00291 #endif 00292 00293 tar = rpmGetPath("%{__tar}", NULL); 00294 if (strcmp(tar, "%{__tar}") == 0) 00295 tar = xstrdup("tar"); 00296 00297 #if defined(RPM_VENDOR_ARK) /* use-gnu-tar-compression-detection */ 00298 /* We leave compression handling for all tar based files up to GNU tar */ 00299 if (compressed == COMPRESSED_ZIP) 00300 #else 00301 if (compressed != COMPRESSED_NOT) 00302 #endif 00303 { 00304 const char *zipper; 00305 int needtar = 1; 00306 00307 switch (compressed) { 00308 case COMPRESSED_NOT: /* XXX can't happen */ 00309 case COMPRESSED_OTHER: 00310 t = "%{__gzip} -dc"; 00311 break; 00312 case COMPRESSED_BZIP2: 00313 t = "%{__bzip2} -dc"; 00314 break; 00315 case COMPRESSED_LZOP: 00316 t = "%{__lzop} -dc"; 00317 break; 00318 case COMPRESSED_LZMA: 00319 t = "%{__lzma} -dc"; 00320 break; 00321 case COMPRESSED_XZ: 00322 t = "%{__xz} -dc"; 00323 break; 00324 case COMPRESSED_ZIP: 00325 #if defined(RPM_VENDOR_OPENPKG) /* use-bsdtar-for-zip-files */ 00326 t = "%{__bsdtar} -x -f"; 00327 #else 00328 if (rpmIsVerbose() && !quietly) 00329 t = "%{__unzip}"; 00330 else 00331 t = "%{__unzip} -qq"; 00332 #endif 00333 needtar = 0; 00334 break; 00335 } 00336 zipper = rpmGetPath(t, NULL); 00337 buf[0] = '\0'; 00338 t = stpcpy(buf, zipper); 00339 zipper = _free(zipper); 00340 *t++ = ' '; 00341 *t++ = '\''; 00342 t = stpcpy(t, fn); 00343 *t++ = '\''; 00344 if (needtar) { 00345 t = stpcpy(t, " | "); 00346 t = stpcpy(t, tar); 00347 t = stpcpy(t, " "); 00348 t = stpcpy(t, taropts); 00349 t = stpcpy(t, " -"); 00350 } 00351 t = stpcpy(t, 00352 "\n" 00353 "STATUS=$?\n" 00354 "if [ $STATUS -ne 0 ]; then\n" 00355 " exit $STATUS\n" 00356 "fi"); 00357 } else { 00358 buf[0] = '\0'; 00359 t = stpcpy(buf, tar); 00360 t = stpcpy(t, " "); 00361 t = stpcpy(t, taropts); 00362 *t++ = ' '; 00363 t = stpcpy(t, fn); 00364 if(rubygem) { 00365 t = stpcpy(t, 00366 "\n" 00367 "if [ -f data.tar.gz ]; then\n" 00368 " tar "); 00369 t = stpcpy(t, taropts); 00370 t = stpcpy(t, 00371 " data.tar.gz\n" 00372 "fi"); 00373 } 00374 } 00375 00376 tar = _free(tar); 00377 Lurlfn = _free(Lurlfn); 00378 return buf; 00379 } 00380 00388 static int doSetupMacro(Spec spec, const char * line) 00389 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00390 /*@modifies spec->buildSubdir, spec->macros, spec->prep, 00391 spec->packages->header, 00392 rpmGlobalMacroContext, fileSystem, internalState @*/ 00393 { 00394 char buf[BUFSIZ]; 00395 rpmiob before = NULL; 00396 rpmiob after = NULL; 00397 poptContext optCon; 00398 int argc; 00399 const char ** argv; 00400 int arg; 00401 const char * optArg; 00402 int rc; 00403 rpmuint32_t num; 00404 rpmRC ec = RPMRC_FAIL; /* XXX assume failure */ 00405 00406 /*@-mods@*/ 00407 leaveDirs = skipDefaultAction = 0; 00408 createDir = quietly = 0; 00409 dirName = NULL; 00410 /*@=mods@*/ 00411 00412 if ((rc = poptParseArgvString(line, &argc, &argv))) { 00413 rpmlog(RPMLOG_ERR, _("Error parsing %%setup: %s\n"), 00414 poptStrerror(rc)); 00415 goto exit; 00416 } 00417 00418 before = rpmiobNew(0); 00419 after = rpmiobNew(0); 00420 00421 optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); 00422 while ((arg = poptGetNextOpt(optCon)) > 0) { 00423 optArg = poptGetOptArg(optCon); 00424 00425 /* We only parse -a and -b here */ 00426 00427 if (parseNum(optArg, &num)) { 00428 rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%setup: %s\n"), 00429 spec->lineNum, (optArg ? optArg : "???")); 00430 optCon = poptFreeContext(optCon); 00431 argv = _free(argv); 00432 goto exit; 00433 } 00434 00435 { const char *chptr = doUntar(spec, num, quietly); 00436 if (chptr == NULL) 00437 goto exit; 00438 00439 (void) rpmiobAppend((arg == 'a' ? after : before), chptr, 1); 00440 } 00441 } 00442 00443 if (arg < -1) { 00444 rpmlog(RPMLOG_ERR, _("line %d: Bad %%setup option %s: %s\n"), 00445 spec->lineNum, 00446 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 00447 poptStrerror(arg)); 00448 optCon = poptFreeContext(optCon); 00449 argv = _free(argv); 00450 goto exit; 00451 } 00452 00453 if (dirName) { 00454 spec->buildSubdir = xstrdup(dirName); 00455 } else { 00456 const char *N, *V; 00457 (void) headerNEVRA(spec->packages->header, &N, NULL, &V, NULL, NULL); 00458 (void) snprintf(buf, sizeof(buf), "%s-%s", N, V); 00459 buf[sizeof(buf)-1] = '\0'; 00460 N = _free(N); 00461 V = _free(V); 00462 spec->buildSubdir = xstrdup(buf); 00463 } 00464 addMacro(spec->macros, "buildsubdir", NULL, spec->buildSubdir, RMIL_SPEC); 00465 00466 optCon = poptFreeContext(optCon); 00467 argv = _free(argv); 00468 00469 /* cd to the build dir */ 00470 { const char * buildDirURL = rpmGenPath(spec->rootURL, "%{_builddir}", ""); 00471 const char *buildDir; 00472 00473 (void) urlPath(buildDirURL, &buildDir); 00474 rc = rpmioMkpath(buildDir, 0755, -1, -1); 00475 sprintf(buf, "cd '%s'", buildDir); 00476 spec->prep = rpmiobAppend(spec->prep, buf, 1); 00477 buildDirURL = _free(buildDirURL); 00478 } 00479 00480 /* delete any old sources */ 00481 if (!leaveDirs) { 00482 sprintf(buf, "rm -rf '%s'", spec->buildSubdir); 00483 spec->prep = rpmiobAppend(spec->prep, buf, 1); 00484 } 00485 00486 /* check if source is a ruby gem */ 00487 { struct Source *sp; 00488 for (sp = spec->sources; sp != NULL; sp = sp->next) { 00489 if ((sp->flags & RPMFILE_SOURCE) && (sp->num == 0)) { 00490 break; 00491 } 00492 } 00493 if (sp != NULL) { 00494 char *t = strrchr(sp->source, '.'); 00495 if(t && !strcasecmp(t, ".gem")) 00496 createDir = 1; 00497 } 00498 } 00499 00500 /* if necessary, create and cd into the proper dir */ 00501 if (createDir) { 00502 char *mkdir_p; 00503 mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL); 00504 if (!mkdir_p) 00505 mkdir_p = xstrdup("mkdir -p"); 00506 sprintf(buf, "%s '%s'\ncd '%s'", 00507 mkdir_p, spec->buildSubdir, spec->buildSubdir); 00508 mkdir_p = _free(mkdir_p); 00509 spec->prep = rpmiobAppend(spec->prep, buf, 1); 00510 } 00511 00512 /* do the default action */ 00513 if (!createDir && !skipDefaultAction) { 00514 const char *chptr = doUntar(spec, 0, quietly); 00515 if (chptr == NULL) 00516 goto exit; 00517 spec->prep = rpmiobAppend(spec->prep, chptr, 1); 00518 } 00519 00520 spec->prep = rpmiobAppend(spec->prep, rpmiobStr(before), 0); 00521 00522 if (!createDir) { 00523 sprintf(buf, "cd '%s'", spec->buildSubdir); 00524 spec->prep = rpmiobAppend(spec->prep, buf, 1); 00525 } 00526 00527 if (createDir && !skipDefaultAction) { 00528 const char * chptr = doUntar(spec, 0, quietly); 00529 if (chptr == NULL) 00530 goto exit; 00531 spec->prep = rpmiobAppend(spec->prep, chptr, 1); 00532 } 00533 00534 spec->prep = rpmiobAppend(spec->prep, rpmiobStr(after), 0); 00535 00536 /* XXX FIXME: owner & group fixes were conditioned on !geteuid() */ 00537 /* Fix the owner, group, and permissions of the setup build tree */ 00538 { /*@observer@*/ static const char *fixmacs[] = 00539 { "%{_fixowner}", "%{_fixgroup}", "%{_fixperms}", NULL }; 00540 const char ** fm; 00541 00542 for (fm = fixmacs; *fm; fm++) { 00543 const char *fix; 00544 fix = rpmExpand(*fm, " .", NULL); 00545 if (fix && *fix != '%') 00546 spec->prep = rpmiobAppend(spec->prep, fix, 1); 00547 fix = _free(fix); 00548 } 00549 } 00550 ec = RPMRC_OK; 00551 00552 exit: 00553 before = rpmiobFree(before); 00554 after = rpmiobFree(after); 00555 return ec; 00556 } 00557 00558 #ifndef DYING 00559 00565 static rpmRC doPatchMacro(Spec spec, const char * line) 00566 /*@globals rpmGlobalMacroContext, h_errno, 00567 fileSystem, internalState @*/ 00568 /*@modifies spec->prep, rpmGlobalMacroContext, 00569 fileSystem, internalState @*/ 00570 { 00571 char *s; 00572 char *opt_b; 00573 char *opt_d; 00574 rpmuint32_t opt_P, opt_p, opt_R, opt_E, opt_F; 00575 char buf[BUFSIZ], *bp; 00576 rpmuint32_t patch_nums[1024]; /* XXX - we can only handle 1024 patches! */ 00577 int patch_index, x; 00578 00579 memset(patch_nums, 0, sizeof(patch_nums)); 00580 opt_P = opt_p = opt_R = opt_E = 0; 00581 opt_F = rpmExpandNumeric("%{?_default_patch_fuzz}%{!?_default_patch_fuzz:-1}"); 00582 opt_b = NULL; 00583 opt_d = NULL; 00584 patch_index = 0; 00585 00586 if (! strchr(" \t\n", line[6])) { 00587 /* %patchN */ 00588 sprintf(buf, "%%patch -P %s", line + 6); 00589 } else { 00590 strcpy(buf, line); 00591 } 00592 00593 /*@-internalglobs@*/ /* FIX: strtok has state */ 00594 for (bp = buf; (s = strtok(bp, " \t\n")) != NULL;) { 00595 if (bp) { /* remove 1st token (%patch) */ 00596 bp = NULL; 00597 continue; 00598 } 00599 if (!strcmp(s, "-P")) { 00600 opt_P = 1; 00601 } else if (!strcmp(s, "-R")) { 00602 opt_R = 1; 00603 } else if (!strcmp(s, "-E")) { 00604 opt_E = 1; 00605 } else if (!strcmp(s, "-b")) { 00606 /* orig suffix */ 00607 opt_b = strtok(NULL, " \t\n"); 00608 if (! opt_b) { 00609 rpmlog(RPMLOG_ERR, 00610 _("line %d: Need arg to %%patch -b: %s\n"), 00611 spec->lineNum, spec->line); 00612 return RPMRC_FAIL; 00613 } 00614 } else if (!strcmp(s, "-z")) { 00615 /* orig suffix */ 00616 opt_b = strtok(NULL, " \t\n"); 00617 if (! opt_b) { 00618 rpmlog(RPMLOG_ERR, 00619 _("line %d: Need arg to %%patch -z: %s\n"), 00620 spec->lineNum, spec->line); 00621 return RPMRC_FAIL; 00622 } 00623 } else if (!strcmp(s, "-F")) { 00624 /* fuzz factor */ 00625 const char * fnum = (!strchr(" \t\n", s[2]) 00626 ? s+2 : strtok(NULL, " \t\n")); 00627 char * end = NULL; 00628 00629 opt_F = (fnum ? strtol(fnum, &end, 10) : 0); 00630 if (! opt_F || *end) { 00631 rpmlog(RPMLOG_ERR, 00632 _("line %d: Bad arg to %%patch -F: %s\n"), 00633 spec->lineNum, spec->line); 00634 return RPMRC_FAIL; 00635 } 00636 } else if (!strcmp(s, "-d")) { 00637 /* subdirectory */ 00638 opt_d = strtok(NULL, " \t\n"); 00639 if (! opt_d) { 00640 rpmlog(RPMLOG_ERR, 00641 _("line %d: Need arg to %%patch -d: %s\n"), 00642 spec->lineNum, spec->line); 00643 return RPMRC_FAIL; 00644 } 00645 } else if (!strncmp(s, "-p", sizeof("-p")-1)) { 00646 /* unfortunately, we must support -pX */ 00647 if (! strchr(" \t\n", s[2])) { 00648 s = s + 2; 00649 } else { 00650 s = strtok(NULL, " \t\n"); 00651 if (s == NULL) { 00652 rpmlog(RPMLOG_ERR, 00653 _("line %d: Need arg to %%patch -p: %s\n"), 00654 spec->lineNum, spec->line); 00655 return RPMRC_FAIL; 00656 } 00657 } 00658 if (parseNum(s, &opt_p)) { 00659 rpmlog(RPMLOG_ERR, 00660 _("line %d: Bad arg to %%patch -p: %s\n"), 00661 spec->lineNum, spec->line); 00662 return RPMRC_FAIL; 00663 } 00664 } else { 00665 /* Must be a patch num */ 00666 if (patch_index == 1024) { 00667 rpmlog(RPMLOG_ERR, _("Too many patches!\n")); 00668 return RPMRC_FAIL; 00669 } 00670 if (parseNum(s, &(patch_nums[patch_index]))) { 00671 rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%patch: %s\n"), 00672 spec->lineNum, spec->line); 00673 return RPMRC_FAIL; 00674 } 00675 patch_index++; 00676 } 00677 } 00678 /*@=internalglobs@*/ 00679 00680 /* All args processed */ 00681 00682 if (! opt_P) { 00683 s = doPatch(spec, 0, opt_p, opt_b, opt_R, opt_E, opt_F, opt_d); 00684 if (s == NULL) 00685 return RPMRC_FAIL; 00686 spec->prep = rpmiobAppend(spec->prep, s, 1); 00687 } 00688 00689 for (x = 0; x < patch_index; x++) { 00690 s = doPatch(spec, patch_nums[x], opt_p, opt_b, opt_R, opt_E, opt_F, opt_d); 00691 if (s == NULL) 00692 return RPMRC_FAIL; 00693 spec->prep = rpmiobAppend(spec->prep, s, 1); 00694 } 00695 00696 return RPMRC_OK; 00697 } 00698 #endif 00699 00700 static void prepFetchVerbose(/*@unused@*/ struct Source *sp, 00701 /*@unused@*/ struct stat *st) 00702 /*@globals internalState @*/ 00703 /*@modifies internalState @*/ 00704 { 00705 char *buf; 00706 size_t buf_len; 00707 int xx; 00708 int i; 00709 00710 if (!(rpmIsVerbose() && !quietly && (rpmBTArgs.buildAmount & RPMBUILD_FETCHSOURCE))) 00711 return; 00712 buf_len = 2*80; 00713 if ((buf = (char *)malloc(buf_len)) == NULL) 00714 return; 00715 xx = snprintf(buf, buf_len, "%s%d:", (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num); 00716 for (i = (int)strlen(buf); i <= 11; i++) 00717 buf[i] = ' '; 00718 xx = snprintf(buf+i, buf_len-i, "%-52.52s", sp->source); 00719 i = (int)strlen(buf); 00720 if (st != NULL) 00721 xx = snprintf(buf+i, buf_len-i, " %9lu Bytes\n", (unsigned long)st->st_size); 00722 else 00723 xx = snprintf(buf+i, buf_len-i, " ...MISSING\n"); 00724 rpmlog(RPMLOG_NOTICE, "%s", buf); 00725 buf = _free(buf); 00726 return; 00727 } 00728 00732 static int prepFetch(Spec spec) 00733 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00734 /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/ 00735 { 00736 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ 00737 const char *Smacro; 00738 #endif 00739 const char *Lmacro, *Lurlfn = NULL; 00740 const char *Rmacro, *Rurlfn = NULL; 00741 struct Source *sp; 00742 struct stat st; 00743 rpmRC rpmrc; 00744 int ec, rc; 00745 char *cp; 00746 00747 /* XXX insure that %{_sourcedir} exists */ 00748 rpmrc = RPMRC_OK; 00749 Lurlfn = rpmGenPath(NULL, "%{?_sourcedir}", NULL); 00750 if (Lurlfn != NULL && *Lurlfn != '\0') 00751 rpmrc = rpmMkdirPath(Lurlfn, "_sourcedir"); 00752 Lurlfn = _free(Lurlfn); 00753 if (rpmrc != RPMRC_OK) 00754 return -1; 00755 00756 /* XXX insure that %{_patchdir} exists */ 00757 rpmrc = RPMRC_OK; 00758 Lurlfn = rpmGenPath(NULL, "%{?_patchdir}", NULL); 00759 if (Lurlfn != NULL && *Lurlfn != '\0') 00760 rpmrc = rpmMkdirPath(Lurlfn, "_patchdir"); 00761 Lurlfn = _free(Lurlfn); 00762 if (rpmrc != RPMRC_OK) 00763 return -1; 00764 00765 /* XXX insure that %{_icondir} exists */ 00766 rpmrc = RPMRC_OK; 00767 Lurlfn = rpmGenPath(NULL, "%{?_icondir}", NULL); 00768 if (Lurlfn != NULL && *Lurlfn != '\0') 00769 rpmrc = rpmMkdirPath(Lurlfn, "_icondir"); 00770 Lurlfn = _free(Lurlfn); 00771 if (rpmrc != RPMRC_OK) 00772 return -1; 00773 00774 if (rpmIsVerbose() && !quietly && (rpmBTArgs.buildAmount & RPMBUILD_FETCHSOURCE)) 00775 rpmlog(RPMLOG_NOTICE, "Checking source and patch file(s):\n"); 00776 00777 ec = 0; 00778 for (sp = spec->sources; sp != NULL; sp = sp->next) { 00779 00780 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ 00781 Smacro = "%{?_specdir}/"; 00782 #endif 00783 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ 00784 if (! (Lmacro = getSourceDir(sp->flags, sp->source))) 00785 #else 00786 if (! (Lmacro = getSourceDir(sp->flags))) 00787 #endif 00788 continue; 00789 if (sp->flags & RPMFILE_SOURCE) { 00790 Rmacro = "%{?_Rsourcedir}/"; 00791 } else 00792 if (sp->flags & RPMFILE_PATCH) { 00793 Rmacro = "%{?_Rpatchdir}/"; 00794 } else 00795 if (sp->flags & RPMFILE_ICON) { 00796 Rmacro = "%{?_Ricondir}/"; 00797 } else 00798 continue; 00799 00800 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */ 00801 /* support splitted source directories, i.e., source files which 00802 are alternatively placed into the .spec directory and picked 00803 up from there, too. */ 00804 Lurlfn = rpmGenPath(NULL, Smacro, sp->source); 00805 rc = Lstat(Lurlfn, &st); 00806 if (rc == 0) { 00807 prepFetchVerbose(sp, &st); 00808 goto bottom; 00809 } 00810 #endif 00811 Lurlfn = rpmGenPath(NULL, Lmacro, sp->source); 00812 rc = Lstat(Lurlfn, &st); 00813 if (rc == 0) { 00814 /*@-noeffect@*/ 00815 prepFetchVerbose(sp, &st); 00816 /*@=noeffect@*/ 00817 goto bottom; 00818 } 00819 /*@-noeffect@*/ 00820 prepFetchVerbose(sp, NULL); 00821 /*@=noeffect@*/ 00822 if (errno != ENOENT) { 00823 ec++; 00824 rpmlog(RPMLOG_ERR, _("Missing %s%d %s: %s\n"), 00825 ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"), 00826 sp->num, sp->source, strerror(ENOENT)); 00827 goto bottom; 00828 } 00829 00830 /* try to fetch via macro-controlled remote locations */ 00831 cp = rpmExpand(Rmacro, NULL); 00832 if (cp != NULL && strcmp(cp, "/") != 0) { 00833 cp = _free(cp); 00834 Rurlfn = rpmGenPath(NULL, Rmacro, sp->source); 00835 if (!(Rurlfn == NULL || Rurlfn[0] == '\0' || !strcmp(Rurlfn, "/") || !strcmp(Lurlfn, Rurlfn))) { 00836 rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"), 00837 (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, Rurlfn); 00838 rc = urlGetFile(Rurlfn, Lurlfn); 00839 if (rc == 0) 00840 goto bottom; 00841 else { 00842 rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"), 00843 (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc)); 00844 ec++; 00845 } 00846 } 00847 } 00848 cp = _free(cp); 00849 00850 /* try to fetch from original location */ 00851 rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"), 00852 (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, sp->fullSource); 00853 rc = urlGetFile(sp->fullSource, Lurlfn); 00854 if (rc == 0) 00855 goto bottom; 00856 else { 00857 rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"), 00858 (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc)); 00859 ec++; 00860 } 00861 00862 rpmlog(RPMLOG_ERR, _("Missing %s%d: %s: %s\n"), 00863 ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"), 00864 sp->num, sp->source, strerror(ENOENT)); 00865 ec++; 00866 00867 bottom: 00868 Lurlfn = _free(Lurlfn); 00869 Rurlfn = _free(Rurlfn); 00870 } 00871 00872 return ec; 00873 } 00874 00875 int parsePrep(Spec spec, int verify) 00876 { 00877 rpmParseState nextPart; 00878 int res, rc; 00879 rpmiob iob; 00880 ARGV_t saveLines = NULL; 00881 ARGV_t lines; 00882 const char * cp; 00883 int xx; 00884 00885 if (spec->prep != NULL) { 00886 rpmlog(RPMLOG_ERR, _("line %d: second %%prep\n"), spec->lineNum); 00887 return RPMRC_FAIL; 00888 } 00889 00890 spec->prep = rpmiobNew(0); 00891 00892 /* There are no options to %prep */ 00893 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) 00894 return PART_NONE; 00895 if (rc) 00896 return rc; 00897 00898 /* Check to make sure that all sources/patches are present. */ 00899 if (verify) { 00900 rc = prepFetch(spec); 00901 if (rc) 00902 return RPMRC_FAIL; 00903 } 00904 00905 iob = rpmiobNew(0); 00906 00907 while ((nextPart = isPart(spec)) == PART_NONE) { 00908 /* Need to expand the macros inline. That way we */ 00909 /* can give good line number information on error. */ 00910 iob = rpmiobAppend(iob, spec->line, 0); 00911 if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { 00912 nextPart = PART_NONE; 00913 break; 00914 } 00915 if (rc) 00916 return rc; 00917 } 00918 00919 xx = argvSplit(&saveLines, rpmiobStr(iob), "\n"); 00920 00921 /*@-usereleased@*/ 00922 for (lines = saveLines; *lines; lines++) { 00923 res = 0; 00924 for (cp = *lines; *cp == ' ' || *cp == '\t'; cp++) 00925 {}; 00926 if (!strncmp(cp, "%setup", sizeof("%setup")-1)) { 00927 res = doSetupMacro(spec, cp); 00928 #ifndef DYING 00929 } else if (! strncmp(cp, "%patch", sizeof("%patch")-1)) { 00930 res = doPatchMacro(spec, cp); 00931 #endif 00932 } else { 00933 spec->prep = rpmiobAppend(spec->prep, *lines, 1); 00934 } 00935 if (res && !spec->force) { 00936 saveLines = argvFree(saveLines); 00937 iob = rpmiobFree(iob); 00938 return res; 00939 } 00940 } 00941 /*@=usereleased@*/ 00942 00943 saveLines = argvFree(saveLines); 00944 iob = rpmiobFree(iob); 00945 00946 return nextPart; 00947 }