00001 #include "system.h"
00002
00003 #include <signal.h>
00004
00005 #include <rpmio.h>
00006 #include <rpmiotypes.h>
00007 #include <rpmlog.h>
00008 #include <rpmurl.h>
00009 #include <rpmmg.h>
00010 #include <argv.h>
00011 #define _MIRE_INTERNAL
00012 #include <mire.h>
00013
00014 #include <rpmtag.h>
00015 #define _RPMEVR_INTERNAL
00016 #include <rpmbuild.h>
00017
00018 #define _RPMNS_INTERNAL
00019 #include <rpmns.h>
00020
00021 #define _RPMFC_INTERNAL
00022 #include <rpmfc.h>
00023
00024 #define _RPMDS_INTERNAL
00025 #include <rpmds.h>
00026 #include <rpmfi.h>
00027
00028 #include "debug.h"
00029
00030
00031
00032
00033
00034 static int _filter_values = 1;
00035
00036 static int _filter_execs = 1;
00037
00040 static int rpmfcExpandAppend( ARGV_t * argvp, const ARGV_t av)
00041
00042
00043
00044 {
00045 ARGV_t argv = *argvp;
00046 int argc = argvCount(argv);
00047 int ac = argvCount(av);
00048 int i;
00049
00050 argv = xrealloc(argv, (argc + ac + 1) * sizeof(*argv));
00051 for (i = 0; i < ac; i++)
00052 argv[argc + i] = rpmExpand(av[i], NULL);
00053 argv[argc + ac] = NULL;
00054 *argvp = argv;
00055 return 0;
00056 }
00057
00068
00069 static rpmiob getOutputFrom( const char * dir, ARGV_t argv,
00070 const char * writePtr, size_t writeBytesLeft,
00071 int failNonZero)
00072
00073
00074 {
00075 pid_t child, reaped;
00076 int toProg[2];
00077 int fromProg[2];
00078 int status;
00079 void *oldhandler;
00080 rpmiob iob = NULL;
00081 int done;
00082
00083
00084 oldhandler = signal(SIGPIPE, SIG_IGN);
00085
00086
00087 toProg[0] = toProg[1] = 0;
00088 fromProg[0] = fromProg[1] = 0;
00089 if (pipe(toProg) < 0 || pipe(fromProg) < 0) {
00090 rpmlog(RPMLOG_ERR, _("Couldn't create pipe for %s: %m\n"), argv[0]);
00091 return NULL;
00092 }
00093
00094 if (!(child = fork())) {
00095 (void) close(toProg[1]);
00096 (void) close(fromProg[0]);
00097
00098 (void) dup2(toProg[0], STDIN_FILENO);
00099 (void) dup2(fromProg[1], STDOUT_FILENO);
00100
00101 (void) close(toProg[0]);
00102 (void) close(fromProg[1]);
00103
00104 if (dir) {
00105 (void) Chdir(dir);
00106 }
00107
00108 rpmlog(RPMLOG_DEBUG, D_("\texecv(%s) pid %d\n"),
00109 argv[0], (unsigned)getpid());
00110
00111 unsetenv("MALLOC_CHECK_");
00112 (void) execvp(argv[0], (char *const *)argv);
00113
00114 rpmlog(RPMLOG_ERR, _("Couldn't exec %s: %s\n"),
00115 argv[0], strerror(errno));
00116 _exit(EXIT_FAILURE);
00117 }
00118 if (child < 0) {
00119 rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"),
00120 argv[0], strerror(errno));
00121 return NULL;
00122 }
00123
00124 (void) close(toProg[0]);
00125 (void) close(fromProg[1]);
00126
00127
00128 (void) fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
00129 (void) fcntl(toProg[1], F_SETFL, O_NONBLOCK);
00130
00131 iob = rpmiobNew(0);
00132
00133 do {
00134 fd_set ibits, obits;
00135 struct timeval tv;
00136 int nfd;
00137 ssize_t nbr;
00138 ssize_t nbw;
00139 int rc;
00140
00141 done = 0;
00142 top:
00143 FD_ZERO(&ibits);
00144 FD_ZERO(&obits);
00145 if (fromProg[0] >= 0) {
00146 FD_SET(fromProg[0], &ibits);
00147 }
00148 if (toProg[1] >= 0) {
00149 FD_SET(toProg[1], &obits);
00150 }
00151
00152 tv.tv_sec = 0;
00153 tv.tv_usec = 10000;
00154 nfd = ((fromProg[0] > toProg[1]) ? fromProg[0] : toProg[1]);
00155 if ((rc = select(nfd, &ibits, &obits, NULL, &tv)) < 0) {
00156 if (errno == EINTR)
00157 goto top;
00158 break;
00159 }
00160
00161
00162 if (toProg[1] >= 0 && FD_ISSET(toProg[1], &obits)) {
00163 if (writePtr && writeBytesLeft > 0) {
00164 if ((nbw = write(toProg[1], writePtr,
00165 ((size_t)1024<writeBytesLeft) ? (size_t)1024 : writeBytesLeft)) < 0)
00166 {
00167 if (errno != EAGAIN) {
00168 perror("getOutputFrom()");
00169 exit(EXIT_FAILURE);
00170 }
00171 nbw = 0;
00172 }
00173 writeBytesLeft -= nbw;
00174 writePtr += nbw;
00175 } else if (toProg[1] >= 0) {
00176 (void) close(toProg[1]);
00177 toProg[1] = -1;
00178 }
00179 }
00180
00181
00182 { char buf[BUFSIZ+1];
00183 while ((nbr = read(fromProg[0], buf, sizeof(buf)-1)) > 0) {
00184 buf[nbr] = '\0';
00185 iob = rpmiobAppend(iob, buf, 0);
00186 }
00187 }
00188
00189
00190 done = (nbr == 0 || (nbr < 0 && errno != EAGAIN));
00191
00192 } while (!done);
00193
00194
00195 if (toProg[1] >= 0)
00196 (void) close(toProg[1]);
00197 if (fromProg[0] >= 0)
00198 (void) close(fromProg[0]);
00199
00200 (void) signal(SIGPIPE, oldhandler);
00201
00202
00203
00204 reaped = waitpid(child, &status, 0);
00205 rpmlog(RPMLOG_DEBUG, D_("\twaitpid(%d) rc %d status %x\n"),
00206 (unsigned)child, (unsigned)reaped, status);
00207
00208 if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
00209 const char *cmd = argvJoin(argv);
00210 int rc = (WIFEXITED(status) ? WEXITSTATUS(status) : -1);
00211
00212 rpmlog(RPMLOG_ERR, _("Command \"%s\" failed, exit(%d)\n"), cmd, rc);
00213 cmd = _free(cmd);
00214 iob = rpmiobFree(iob);
00215 return NULL;
00216 }
00217 if (writeBytesLeft) {
00218 rpmlog(RPMLOG_ERR, _("failed to write all data to %s\n"), argv[0]);
00219 iob = rpmiobFree(iob);
00220 return NULL;
00221 }
00222 return iob;
00223 }
00224
00225 int rpmfcExec(ARGV_t av, rpmiob iob_stdin, rpmiob * iob_stdoutp,
00226 int failnonzero)
00227 {
00228 const char * s = NULL;
00229 ARGV_t xav = NULL;
00230 ARGV_t pav = NULL;
00231 int pac = 0;
00232 int ec = -1;
00233 rpmiob iob = NULL;
00234 const char * buf_stdin = NULL;
00235 size_t buf_stdin_len = 0;
00236 int xx;
00237
00238 if (iob_stdoutp)
00239 *iob_stdoutp = NULL;
00240 if (!(av && *av))
00241 goto exit;
00242
00243
00244 s = rpmExpand(av[0], NULL);
00245 if (!(s && *s))
00246 goto exit;
00247
00248
00249 pac = 0;
00250 xx = poptParseArgvString(s, &pac, (const char ***)&pav);
00251 if (!(xx == 0 && pac > 0 && pav != NULL))
00252 goto exit;
00253
00254
00255 xav = NULL;
00256 xx = argvAppend(&xav, pav);
00257 if (av[1])
00258 xx = rpmfcExpandAppend(&xav, av + 1);
00259
00260 if (iob_stdin != NULL) {
00261 buf_stdin = rpmiobStr(iob_stdin);
00262 buf_stdin_len = rpmiobLen(iob_stdin);
00263 }
00264
00265
00266 iob = getOutputFrom(NULL, xav, buf_stdin, buf_stdin_len, failnonzero);
00267
00268 if (iob_stdoutp != NULL) {
00269 *iob_stdoutp = iob;
00270 iob = NULL;
00271 }
00272
00273 ec = 0;
00274
00275 exit:
00276 iob = rpmiobFree(iob);
00277 xav = argvFree(xav);
00278 pav = _free(pav);
00279 s = _free(s);
00280 return ec;
00281 }
00282
00285 static int rpmfcSaveArg( ARGV_t * argvp, const char * key)
00286
00287
00288 {
00289 int rc = 0;
00290
00291 if (argvSearch(*argvp, key, NULL) == NULL) {
00292 rc = argvAdd(argvp, key);
00293 rc = argvSort(*argvp, NULL);
00294 }
00295 return rc;
00296 }
00297
00300 static char * rpmfcFileDep( char * buf, size_t ix,
00301 rpmds ds)
00302
00303
00304
00305 {
00306 rpmTag tagN = rpmdsTagN(ds);
00307 char deptype = 'X';
00308
00309 buf[0] = '\0';
00310 switch (tagN) {
00311 default:
00312 assert(0);
00313 break;
00314 case RPMTAG_PROVIDENAME:
00315 deptype = 'P';
00316 break;
00317 case RPMTAG_REQUIRENAME:
00318 deptype = 'R';
00319 break;
00320 }
00321
00322 if (ds != NULL)
00323 sprintf(buf, "%08u%c %s %s 0x%08x", (unsigned)ix, deptype,
00324 rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
00325
00326 return buf;
00327 };
00328
00329
00330 static void * rpmfcExpandRegexps(const char * str, int * nmirep)
00331
00332
00333 {
00334 ARGV_t av = NULL;
00335 int ac = 0;
00336 miRE mire = NULL;
00337 int nmire = 0;
00338 const char * s;
00339 int xx;
00340 int i;
00341
00342 s = rpmExpand(str, NULL);
00343 if (s) {
00344 xx = poptParseArgvString(s, &ac, (const char ***)&av);
00345 s = _free(s);
00346 }
00347 if (ac == 0 || av == NULL || *av == NULL)
00348 goto exit;
00349
00350 for (i = 0; i < ac; i++) {
00351 xx = mireAppend(RPMMIRE_REGEX, 0, av[i], NULL, &mire, &nmire);
00352
00353 if (xx) {
00354 rpmlog(RPMLOG_NOTICE,
00355 _("Compilation of pattern '%s'"
00356 " (expanded from '%s') failed. Skipping ...\n"),
00357 av[i], str);
00358 nmire--;
00359 }
00360 }
00361 if (nmire == 0)
00362 mire = mireFree(mire);
00363
00364 exit:
00365 av = _free(av);
00366 if (nmirep)
00367 *nmirep = nmire;
00368 return mire;
00369 }
00370
00371 static int rpmfcMatchRegexps(void * mires, int nmire,
00372 const char * str, char deptype)
00373
00374 {
00375 miRE mire = mires;
00376 int xx;
00377 int i;
00378
00379 for (i = 0; i < nmire; i++) {
00380 rpmlog(RPMLOG_DEBUG, D_("Checking %c: '%s'\n"), deptype, str);
00381 if ((xx = mireRegexec(mire + i, str, 0)) < 0)
00382 continue;
00383 rpmlog(RPMLOG_NOTICE, _("Skipping %c: '%s'\n"), deptype, str);
00384 return 1;
00385 }
00386 return 0;
00387 }
00388
00389
00390 static void * rpmfcFreeRegexps( void * mires, int nmire)
00391
00392 {
00393 miRE mire = mires;
00394
00395 return mireFreeAll(mire, nmire);
00396
00397 }
00398
00406 static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char * nsdep)
00407
00408
00409 {
00410 miRE mire = NULL;
00411 int nmire = 0;
00412 const char * fn = fc->fn[fc->ix];
00413 char buf[BUFSIZ];
00414 rpmiob iob_stdout = NULL;
00415 rpmiob iob_stdin;
00416 const char *av[2];
00417 rpmds * depsp, ds;
00418 const char * N;
00419 const char * EVR;
00420 rpmTag tagN;
00421 evrFlags Flags;
00422 evrFlags dsContext;
00423 ARGV_t pav;
00424 const char * s;
00425 int pac;
00426 int xx;
00427 int i;
00428
00429 switch (deptype) {
00430 default:
00431 return -1;
00432 break;
00433 case 'P':
00434 if (fc->skipProv)
00435 return 0;
00436 xx = snprintf(buf, sizeof(buf), "%%{?__%s_provides}", nsdep);
00437 depsp = &fc->provides;
00438 dsContext = RPMSENSE_FIND_PROVIDES;
00439 tagN = RPMTAG_PROVIDENAME;
00440 mire = fc->Pmires;
00441 nmire = fc->Pnmire;
00442 break;
00443 case 'R':
00444 if (fc->skipReq)
00445 return 0;
00446 xx = snprintf(buf, sizeof(buf), "%%{?__%s_requires}", nsdep);
00447 depsp = &fc->requires;
00448 dsContext = RPMSENSE_FIND_REQUIRES;
00449 tagN = RPMTAG_REQUIRENAME;
00450 mire = fc->Rmires;
00451 nmire = fc->Rnmire;
00452 break;
00453 }
00454 buf[sizeof(buf)-1] = '\0';
00455 av[0] = buf;
00456 av[1] = NULL;
00457
00458 iob_stdin = rpmiobNew(0);
00459 iob_stdin = rpmiobAppend(iob_stdin, fn, 1);
00460 iob_stdout = NULL;
00461 xx = rpmfcExec(av, iob_stdin, &iob_stdout, 0);
00462 iob_stdin = rpmiobFree(iob_stdin);
00463
00464 if (xx == 0 && iob_stdout != NULL) {
00465 pav = NULL;
00466 xx = argvSplit(&pav, rpmiobStr(iob_stdout), " \t\n\r");
00467 pac = argvCount(pav);
00468 if (pav)
00469 for (i = 0; i < pac; i++) {
00470 N = pav[i];
00471 EVR = "";
00472 Flags = dsContext;
00473 if (pav[i+1] && strchr("=<>", *pav[i+1])) {
00474 i++;
00475 for (s = pav[i]; *s; s++) {
00476 switch(*s) {
00477 default:
00478 assert(*s != '\0');
00479 break;
00480 case '=':
00481 Flags |= RPMSENSE_EQUAL;
00482 break;
00483 case '<':
00484 Flags |= RPMSENSE_LESS;
00485 break;
00486 case '>':
00487 Flags |= RPMSENSE_GREATER;
00488 break;
00489 }
00490 }
00491 i++;
00492 EVR = pav[i];
00493 assert(EVR != NULL);
00494 }
00495
00496 if (_filter_values && rpmfcMatchRegexps(mire, nmire, N, deptype))
00497 continue;
00498
00499
00500 if (!fc->tracked && deptype == 'P' && *EVR != '\0') {
00501 ds = rpmdsSingle(RPMTAG_REQUIRENAME,
00502 "rpmlib(VersionedDependencies)", "3.0.3-1",
00503 RPMSENSE_RPMLIB|(RPMSENSE_LESS|RPMSENSE_EQUAL));
00504 xx = rpmdsMerge(&fc->requires, ds);
00505 (void)rpmdsFree(ds);
00506 ds = NULL;
00507 fc->tracked = 1;
00508 }
00509
00510 ds = rpmdsSingle(tagN, N, EVR, Flags);
00511
00512
00513 xx = rpmdsMerge(depsp, ds);
00514
00515
00516 xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
00517
00518 (void)rpmdsFree(ds);
00519 ds = NULL;
00520 }
00521
00522 pav = argvFree(pav);
00523 }
00524 iob_stdout = rpmiobFree(iob_stdout);
00525
00526 return 0;
00527 }
00528
00531
00532
00533 static struct rpmfcTokens_s rpmfcTokens[] = {
00534 { "directory", RPMFC_DIRECTORY|RPMFC_INCLUDE },
00535
00536 { " shared object", RPMFC_LIBRARY },
00537 { " executable", RPMFC_EXECUTABLE },
00538 { " statically linked", RPMFC_STATIC },
00539 { " not stripped", RPMFC_NOTSTRIPPED },
00540 { " archive", RPMFC_ARCHIVE },
00541
00542 { "MIPS, N32 MIPS32", RPMFC_ELFMIPSN32|RPMFC_INCLUDE },
00543 { "ELF 32-bit", RPMFC_ELF32|RPMFC_INCLUDE },
00544 { "ELF 64-bit", RPMFC_ELF64|RPMFC_INCLUDE },
00545
00546 { " script", RPMFC_SCRIPT },
00547 { " text", RPMFC_TEXT },
00548 { " document", RPMFC_DOCUMENT },
00549
00550 { " compressed", RPMFC_COMPRESSED },
00551
00552 { "troff or preprocessor input", RPMFC_MANPAGE|RPMFC_INCLUDE },
00553 { "GNU Info", RPMFC_MANPAGE|RPMFC_INCLUDE },
00554
00555 { "perl script text", RPMFC_PERL|RPMFC_INCLUDE },
00556 { "Perl5 module source text", RPMFC_PERL|RPMFC_MODULE|RPMFC_INCLUDE },
00557
00558 { "PHP script text", RPMFC_PHP|RPMFC_INCLUDE },
00559
00560
00561
00562 { " /usr/bin/python", RPMFC_PYTHON|RPMFC_INCLUDE },
00563 { "python ", RPMFC_PYTHON|RPMFC_INCLUDE },
00564
00565 { "libtool library ", RPMFC_LIBTOOL|RPMFC_INCLUDE },
00566 { "pkgconfig ", RPMFC_PKGCONFIG|RPMFC_INCLUDE },
00567
00568 { "Bourne ", RPMFC_BOURNE|RPMFC_INCLUDE },
00569 { "Bourne-Again ", RPMFC_BOURNE|RPMFC_INCLUDE },
00570
00571 { "Java ", RPMFC_JAVA|RPMFC_INCLUDE },
00572
00573 { "Mono/.Net assembly", RPMFC_MONO|RPMFC_INCLUDE },
00574
00575 { "current ar archive", RPMFC_STATIC|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_INCLUDE },
00576
00577 { "Zip archive data", RPMFC_COMPRESSED|RPMFC_ARCHIVE|RPMFC_INCLUDE },
00578 { "tar archive", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00579 { "cpio archive", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00580 { "RPM v3", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00581 { "RPM v4", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00582
00583 { " image", RPMFC_IMAGE|RPMFC_INCLUDE },
00584 { " font", RPMFC_FONT|RPMFC_INCLUDE },
00585 { " Font", RPMFC_FONT|RPMFC_INCLUDE },
00586
00587 { " commands", RPMFC_SCRIPT|RPMFC_INCLUDE },
00588 { " script", RPMFC_SCRIPT|RPMFC_INCLUDE },
00589
00590 { "empty", RPMFC_WHITE|RPMFC_INCLUDE },
00591
00592 { "HTML", RPMFC_WHITE|RPMFC_INCLUDE },
00593 { "SGML", RPMFC_WHITE|RPMFC_INCLUDE },
00594 { "XML", RPMFC_WHITE|RPMFC_INCLUDE },
00595
00596 { " program text", RPMFC_WHITE|RPMFC_INCLUDE },
00597 { " source", RPMFC_WHITE|RPMFC_INCLUDE },
00598 { "GLS_BINARY_LSB_FIRST", RPMFC_WHITE|RPMFC_INCLUDE },
00599 { " DB ", RPMFC_WHITE|RPMFC_INCLUDE },
00600
00601 { "ASCII English text", RPMFC_WHITE|RPMFC_INCLUDE },
00602 { "ASCII text", RPMFC_WHITE|RPMFC_INCLUDE },
00603 { "ISO-8859 text", RPMFC_WHITE|RPMFC_INCLUDE },
00604
00605 { "symbolic link to", RPMFC_SYMLINK },
00606 { "socket", RPMFC_DEVICE },
00607 { "special", RPMFC_DEVICE },
00608
00609 { "ASCII", RPMFC_WHITE },
00610 { "ISO-8859", RPMFC_WHITE },
00611
00612 { "data", RPMFC_WHITE },
00613
00614 { "application", RPMFC_WHITE },
00615 { "boot", RPMFC_WHITE },
00616 { "catalog", RPMFC_WHITE },
00617 { "code", RPMFC_WHITE },
00618 { "file", RPMFC_WHITE },
00619 { "format", RPMFC_WHITE },
00620 { "message", RPMFC_WHITE },
00621 { "program", RPMFC_WHITE },
00622
00623 { "broken symbolic link to ", RPMFC_WHITE|RPMFC_ERROR },
00624 { "can't read", RPMFC_WHITE|RPMFC_ERROR },
00625 { "can't stat", RPMFC_WHITE|RPMFC_ERROR },
00626 { "executable, can't read", RPMFC_WHITE|RPMFC_ERROR },
00627 { "core file", RPMFC_WHITE|RPMFC_ERROR },
00628
00629 { NULL, RPMFC_BLACK }
00630 };
00631
00632
00633 int rpmfcColoring(const char * fmstr)
00634 {
00635 rpmfcToken fct;
00636 int fcolor = RPMFC_BLACK;
00637
00638 for (fct = rpmfcTokens; fct->token != NULL; fct++) {
00639 if (strstr(fmstr, fct->token) == NULL)
00640 continue;
00641 fcolor |= fct->colors;
00642 if (fcolor & RPMFC_INCLUDE)
00643 return fcolor;
00644 }
00645 return fcolor;
00646 }
00647
00648 void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
00649 {
00650 int fcolor;
00651 int ndx;
00652 int cx;
00653 int dx;
00654 size_t fx;
00655
00656 unsigned nprovides;
00657 unsigned nrequires;
00658
00659 if (fp == NULL) fp = stderr;
00660
00661 if (msg)
00662 fprintf(fp, "===================================== %s\n", msg);
00663
00664 nprovides = rpmdsCount(fc->provides);
00665 nrequires = rpmdsCount(fc->requires);
00666
00667 if (fc)
00668 for (fx = 0; fx < fc->nfiles; fx++) {
00669 assert(fx < fc->fcdictx->nvals);
00670 cx = fc->fcdictx->vals[fx];
00671 assert(fx < fc->fcolor->nvals);
00672 fcolor = fc->fcolor->vals[fx];
00673
00674 fprintf(fp, "%3d %s", (int)fx, fc->fn[fx]);
00675 if (fcolor != RPMFC_BLACK)
00676 fprintf(fp, "\t0x%x", fc->fcolor->vals[fx]);
00677 else
00678 fprintf(fp, "\t%s", fc->cdict[cx]);
00679 fprintf(fp, "\n");
00680
00681 if (fc->fddictx == NULL || fc->fddictn == NULL)
00682 continue;
00683
00684 assert(fx < fc->fddictx->nvals);
00685 dx = fc->fddictx->vals[fx];
00686 assert(fx < fc->fddictn->nvals);
00687 ndx = fc->fddictn->vals[fx];
00688
00689 while (ndx-- > 0) {
00690 const char * depval;
00691 unsigned char deptype;
00692 unsigned ix;
00693
00694 ix = fc->ddictx->vals[dx++];
00695 deptype = ((ix >> 24) & 0xff);
00696 ix &= 0x00ffffff;
00697 depval = NULL;
00698 switch (deptype) {
00699 default:
00700 assert(depval != NULL);
00701 break;
00702 case 'P':
00703 if (nprovides > 0) {
00704 assert(ix < nprovides);
00705 (void) rpmdsSetIx(fc->provides, ix-1);
00706 if (rpmdsNext(fc->provides) >= 0)
00707 depval = rpmdsDNEVR(fc->provides);
00708 }
00709 break;
00710 case 'R':
00711 if (nrequires > 0) {
00712 assert(ix < nrequires);
00713 (void) rpmdsSetIx(fc->requires, ix-1);
00714 if (rpmdsNext(fc->requires) >= 0)
00715 depval = rpmdsDNEVR(fc->requires);
00716 }
00717 break;
00718 }
00719 if (depval)
00720 fprintf(fp, "\t%s\n", depval);
00721 }
00722 }
00723 }
00724
00730 static int rpmfcSCRIPT(rpmfc fc)
00731
00732
00733 {
00734 const char * fn = fc->fn[fc->ix];
00735 const char * bn;
00736 rpmds ds;
00737 char buf[BUFSIZ];
00738 FILE * fp;
00739 char * s, * se;
00740 int i;
00741 int is_executable;
00742 int xx;
00743
00744
00745 { struct stat sb, * st = &sb;
00746 if (stat(fn, st) != 0)
00747 return -1;
00748 is_executable = (int)(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
00749 }
00750
00751 fp = fopen(fn, "r");
00752 if (fp == NULL || ferror(fp)) {
00753 if (fp) (void) fclose(fp);
00754 return -1;
00755 }
00756
00757
00758 for (i = 0; i < 10; i++) {
00759
00760 s = fgets(buf, sizeof(buf) - 1, fp);
00761 if (s == NULL || ferror(fp) || feof(fp))
00762 break;
00763 s[sizeof(buf)-1] = '\0';
00764 if (!(s[0] == '#' && s[1] == '!'))
00765 continue;
00766 s += 2;
00767
00768 while (*s && strchr(" \t\n\r", *s) != NULL)
00769 s++;
00770 if (*s == '\0')
00771 continue;
00772 if (*s != '/')
00773 continue;
00774
00775 for (se = s+1; *se; se++) {
00776 if (strchr(" \t\n\r", *se) != NULL)
00777 break;
00778 }
00779 *se = '\0';
00780 se++;
00781
00782 if (!_filter_values
00783 || (!fc->skipReq
00784 && !rpmfcMatchRegexps(fc->Rmires, fc->Rnmire, s, 'R')))
00785 if (is_executable) {
00786
00787 ds = rpmdsSingle(RPMTAG_REQUIRENAME, s, "", RPMSENSE_FIND_REQUIRES);
00788 xx = rpmdsMerge(&fc->requires, ds);
00789
00790
00791 xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(se, fc->ix, ds));
00792
00793 (void)rpmdsFree(ds);
00794 ds = NULL;
00795 }
00796
00797
00798
00799
00800 bn = basename(s);
00801
00802 if (!strcmp(bn, "perl"))
00803 fc->fcolor->vals[fc->ix] |= RPMFC_PERL;
00804 else if (!strncmp(bn, "python", sizeof("python")-1))
00805 fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
00806 else if (!strncmp(bn, "php", sizeof("php")-1))
00807 fc->fcolor->vals[fc->ix] |= RPMFC_PHP;
00808
00809 break;
00810 }
00811
00812 (void) fclose(fp);
00813
00814 if (fc->fcolor->vals[fc->ix] & RPMFC_PERL) {
00815 if (strncmp(fn, "/usr/share/doc/", sizeof("/usr/share/doc/")-1)) {
00816 if (fc->fcolor->vals[fc->ix] & RPMFC_MODULE)
00817 xx = rpmfcHelper(fc, 'P', "perl");
00818 if (is_executable || (fc->fcolor->vals[fc->ix] & RPMFC_MODULE))
00819 xx = rpmfcHelper(fc, 'R', "perl");
00820 }
00821 } else
00822 if (fc->fcolor->vals[fc->ix] & RPMFC_PYTHON) {
00823 xx = rpmfcHelper(fc, 'P', "python");
00824 #ifdef NOTYET
00825 if (is_executable)
00826 #endif
00827 xx = rpmfcHelper(fc, 'R', "python");
00828 } else
00829 if (fc->fcolor->vals[fc->ix] & RPMFC_LIBTOOL) {
00830 xx = rpmfcHelper(fc, 'P', "libtool");
00831 #ifdef NOTYET
00832 if (is_executable)
00833 #endif
00834 xx = rpmfcHelper(fc, 'R', "libtool");
00835 } else
00836 if (fc->fcolor->vals[fc->ix] & RPMFC_PKGCONFIG) {
00837 xx = rpmfcHelper(fc, 'P', "pkgconfig");
00838 #ifdef NOTYET
00839 if (is_executable)
00840 #endif
00841 xx = rpmfcHelper(fc, 'R', "pkgconfig");
00842 } else
00843 if (fc->fcolor->vals[fc->ix] & RPMFC_BOURNE) {
00844 #ifdef NOTYET
00845 xx = rpmfcHelper(fc, 'P', "executable");
00846 #endif
00847 if (is_executable)
00848 xx = rpmfcHelper(fc, 'R', "executable");
00849 } else
00850 if (fc->fcolor->vals[fc->ix] & RPMFC_PHP) {
00851 xx = rpmfcHelper(fc, 'P', "php");
00852 if (is_executable)
00853 xx = rpmfcHelper(fc, 'R', "php");
00854 } else
00855 if (fc->fcolor->vals[fc->ix] & RPMFC_MONO) {
00856 xx = rpmfcHelper(fc, 'P', "mono");
00857 if (is_executable)
00858 xx = rpmfcHelper(fc, 'R', "mono");
00859 }
00860 return 0;
00861 }
00862
00869 static int rpmfcMergePR(void * context, rpmds ds)
00870
00871
00872 {
00873 rpmfc fc = context;
00874 char buf[BUFSIZ];
00875 int rc = 0;
00876
00877 if (_rpmfc_debug < 0)
00878 fprintf(stderr, "*** rpmfcMergePR(%p, %p) %s\n", context, ds, tagName(rpmdsTagN(ds)));
00879 switch(rpmdsTagN(ds)) {
00880 default:
00881 rc = -1;
00882 break;
00883 case RPMTAG_PROVIDENAME:
00884 if (!_filter_values
00885 || (!fc->skipProv
00886 && !rpmfcMatchRegexps(fc->Pmires, fc->Pnmire, ds->N[0], 'P')))
00887 {
00888
00889 rc = rpmdsMerge(&fc->provides, ds);
00890
00891
00892 buf[0] = '\0';
00893 rc = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
00894 }
00895 break;
00896 case RPMTAG_REQUIRENAME:
00897 if (!_filter_values
00898 || (!fc->skipReq
00899 && !rpmfcMatchRegexps(fc->Rmires, fc->Rnmire, ds->N[0], 'R')))
00900 {
00901
00902 rc = rpmdsMerge(&fc->requires, ds);
00903
00904
00905 buf[0] = '\0';
00906 rc = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
00907 }
00908 break;
00909 }
00910 return rc;
00911 }
00912
00918 static int rpmfcELF(rpmfc fc)
00919
00920
00921 {
00922 const char * fn = fc->fn[fc->ix];
00923 int flags = 0;
00924
00925 if (fc->skipProv)
00926 flags |= RPMELF_FLAG_SKIPPROVIDES;
00927 if (fc->skipReq)
00928 flags |= RPMELF_FLAG_SKIPREQUIRES;
00929
00930 return rpmdsELF(fn, flags, rpmfcMergePR, fc);
00931 }
00932
00933 typedef struct rpmfcApplyTbl_s {
00934 int (*func) (rpmfc fc);
00935 int colormask;
00936 } * rpmfcApplyTbl;
00937
00941
00942
00943 static struct rpmfcApplyTbl_s rpmfcApplyTable[] = {
00944 { rpmfcELF, RPMFC_ELF },
00945 { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PERL|RPMFC_PYTHON|RPMFC_LIBTOOL|RPMFC_PKGCONFIG|RPMFC_BOURNE|RPMFC_JAVA|RPMFC_PHP|RPMFC_MONO) },
00946 { NULL, 0 }
00947 };
00948
00949
00950 rpmRC rpmfcApply(rpmfc fc)
00951 {
00952 rpmfcApplyTbl fcat;
00953 const char * s;
00954 char * se;
00955 rpmds ds;
00956 const char * fn;
00957 const char * N;
00958 const char * EVR;
00959 evrFlags Flags;
00960 unsigned char deptype;
00961 int nddict;
00962 int previx;
00963 unsigned int val;
00964 int dix;
00965 int ix;
00966 int i;
00967 int xx;
00968 int skipping;
00969
00970 miRE mire;
00971 int skipProv = fc->skipProv;
00972 int skipReq = fc->skipReq;
00973 int j;
00974
00975 if (_filter_execs) {
00976 fc->Pnmire = 0;
00977 fc->PFnmire = 0;
00978 fc->Rnmire = 0;
00979 fc->RFnmire = 0;
00980
00981 fc->PFmires = rpmfcExpandRegexps("%{__noautoprovfiles}", &fc->PFnmire);
00982 fc->RFmires = rpmfcExpandRegexps("%{__noautoreqfiles}", &fc->RFnmire);
00983 fc->Pmires = rpmfcExpandRegexps("%{__noautoprov}", &fc->Pnmire);
00984 fc->Rmires = rpmfcExpandRegexps("%{__noautoreq}", &fc->Rnmire);
00985 rpmlog(RPMLOG_DEBUG, D_("%i _noautoprov patterns.\n"), fc->Pnmire);
00986 rpmlog(RPMLOG_DEBUG, D_("%i _noautoreq patterns.\n"), fc->Rnmire);
00987 }
00988
00989
00990 assert(fc->fn != NULL);
00991
00992 for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) {
00993
00994
00995
00996 { fn = strstr(fc->fn[fc->ix], "/usr/lib");
00997 if (fn) {
00998 fn += sizeof("/usr/lib")-1;
00999 if ((fn[0] == '3' && fn[1] == '2') ||
01000 (fn[0] == '6' && fn[1] == '4'))
01001 fn += 2;
01002 if (!strncmp(fn, "/python", sizeof("/python")-1))
01003 fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
01004 }
01005 }
01006
01007 if (fc->fcolor->vals[fc->ix])
01008 for (fcat = rpmfcApplyTable; fcat->func != NULL; fcat++) {
01009 if (!(fc->fcolor->vals[fc->ix] & fcat->colormask))
01010 continue;
01011
01012 if (_filter_execs) {
01013 fc->skipProv = skipProv;
01014 fc->skipReq = skipReq;
01015 if ((mire = fc->PFmires) != NULL)
01016 for (j = 0; j < fc->PFnmire; j++, mire++) {
01017 fn = fc->fn[fc->ix] + fc->brlen;
01018 if ((xx = mireRegexec(mire, fn, 0)) < 0)
01019 continue;
01020 rpmlog(RPMLOG_NOTICE, _("skipping %s provides detection\n"),
01021 fn);
01022 fc->skipProv = 1;
01023 break;
01024 }
01025 if ((mire = fc->RFmires) != NULL)
01026 for (j = 0; j < fc->RFnmire; j++, mire++) {
01027 fn = fc->fn[fc->ix] + fc->brlen;
01028 if ((xx = mireRegexec(mire, fn, 0)) < 0)
01029 continue;
01030 rpmlog(RPMLOG_NOTICE, _("skipping %s requires detection\n"),
01031 fn);
01032 fc->skipReq = 1;
01033 break;
01034 }
01035 }
01036
01037 xx = (*fcat->func) (fc);
01038 }
01039 }
01040
01041 if (_filter_execs) {
01042 fc->PFmires = rpmfcFreeRegexps(fc->PFmires, fc->PFnmire);
01043 fc->RFmires = rpmfcFreeRegexps(fc->RFmires, fc->RFnmire);
01044 fc->Pmires = rpmfcFreeRegexps(fc->Pmires, fc->Pnmire);
01045 fc->Rmires = rpmfcFreeRegexps(fc->Rmires, fc->Rnmire);
01046 }
01047 fc->skipProv = skipProv;
01048 fc->skipReq = skipReq;
01049
01050
01051 nddict = argvCount(fc->ddict);
01052 previx = -1;
01053 for (i = 0; i < nddict; i++) {
01054 s = fc->ddict[i];
01055
01056
01057 ix = strtol(s, &se, 10);
01058 assert(se != NULL);
01059 deptype = *se++;
01060 se++;
01061 N = se;
01062 while (*se && *se != ' ')
01063 se++;
01064 *se++ = '\0';
01065 EVR = se;
01066 while (*se && *se != ' ')
01067 se++;
01068 *se++ = '\0';
01069 Flags = strtol(se, NULL, 16);
01070
01071 dix = -1;
01072 skipping = 0;
01073 switch (deptype) {
01074 default:
01075 break;
01076 case 'P':
01077 skipping = fc->skipProv;
01078 ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
01079 dix = rpmdsFind(fc->provides, ds);
01080 (void)rpmdsFree(ds);
01081 ds = NULL;
01082 break;
01083 case 'R':
01084 skipping = fc->skipReq;
01085 ds = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags);
01086 dix = rpmdsFind(fc->requires, ds);
01087 (void)rpmdsFree(ds);
01088 ds = NULL;
01089 break;
01090 }
01091
01092
01093 #if 0
01094 assert(dix >= 0);
01095 #else
01096 if (dix < 0)
01097 continue;
01098 #endif
01099
01100 val = (deptype << 24) | (dix & 0x00ffffff);
01101 xx = argiAdd(&fc->ddictx, -1, val);
01102
01103 if (previx != ix) {
01104 previx = ix;
01105 xx = argiAdd(&fc->fddictx, ix, argiCount(fc->ddictx)-1);
01106 }
01107 if (fc->fddictn && fc->fddictn->vals && !skipping)
01108 fc->fddictn->vals[ix]++;
01109 }
01110
01111 return RPMRC_OK;
01112 }
01113
01114 rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpmuint16_t * fmode)
01115 {
01116 ARGV_t fcav = NULL;
01117 ARGV_t dav;
01118 rpmmg mg = NULL;
01119 const char * s, * se;
01120 size_t slen;
01121 int fcolor;
01122 int xx;
01123 const char * magicfile = NULL;
01124
01125 if (fc == NULL || argv == NULL)
01126 return RPMRC_OK;
01127
01128 magicfile = rpmExpand("%{?_rpmfc_magic_path}", NULL);
01129 if (magicfile == NULL || *magicfile == '\0')
01130 magicfile = _free(magicfile);
01131 mg = rpmmgNew(magicfile, 0);
01132 assert(mg != NULL);
01133
01134 fc->nfiles = argvCount(argv);
01135
01136
01137 xx = argiAdd(&fc->fddictx, fc->nfiles-1, 0);
01138 xx = argiAdd(&fc->fddictn, fc->nfiles-1, 0);
01139
01140
01141 xx = argvAdd(&fc->cdict, "");
01142 xx = argvAdd(&fc->cdict, "directory");
01143
01144 for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
01145 const char * ftype;
01146 int freeftype;
01147 rpmuint16_t mode = (fmode ? fmode[fc->ix] : 0);
01148 int urltype;
01149
01150 ftype = ""; freeftype = 0;
01151 urltype = urlPath(argv[fc->ix], &s);
01152 assert(s != NULL && *s == '/');
01153 slen = strlen(s);
01154
01155 switch (mode & S_IFMT) {
01156 case S_IFCHR: ftype = "character special"; break;
01157 case S_IFBLK: ftype = "block special"; break;
01158 #if defined(S_IFIFO)
01159 case S_IFIFO: ftype = "fifo (named pipe)"; break;
01160 #endif
01161 #if defined(S_IFSOCK)
01162
01163 case S_IFSOCK: ftype = "socket"; break;
01164
01165 #endif
01166 case S_IFDIR:
01167 case S_IFLNK:
01168 case S_IFREG:
01169 default:
01170
01171 #define _suffix(_s, _x) \
01172 (slen >= sizeof(_x) && !strcmp((_s)+slen-(sizeof(_x)-1), (_x)))
01173
01174
01175 if (_suffix(s, ".pm"))
01176 ftype = "Perl5 module source text";
01177
01178
01179 else if (_suffix(s, ".jar"))
01180 ftype = "Java archive file";
01181
01182
01183 else if (_suffix(s, ".class"))
01184 ftype = "Java class file";
01185
01186
01187 else if (_suffix(s, ".la"))
01188 ftype = "libtool library file";
01189
01190
01191 else if (_suffix(s, ".pc"))
01192 ftype = "pkgconfig file";
01193
01194
01195 else if (_suffix(s, ".php"))
01196 ftype = "PHP script text";
01197
01198
01199 else if (slen >= fc->brlen+sizeof("/dev/") && !strncmp(s+fc->brlen, "/dev/", sizeof("/dev/")-1))
01200 ftype = "";
01201 else if (magicfile) {
01202 ftype = rpmmgFile(mg, s);
01203 assert(ftype != NULL);
01204 freeftype = 1;
01205 }
01206 break;
01207 }
01208
01209 se = ftype;
01210
01211 if (_rpmfc_debug)
01212 rpmlog(RPMLOG_DEBUG, "%s: %s\n", s, se);
01213
01214
01215 xx = argvAdd(&fc->fn, s);
01216
01217
01218 xx = argvAdd(&fcav, se);
01219
01220
01221 fcolor = rpmfcColoring(se);
01222 xx = argiAdd(&fc->fcolor, (int)fc->ix, fcolor);
01223
01224 if (fcolor != RPMFC_WHITE && (fcolor & RPMFC_INCLUDE))
01225 xx = rpmfcSaveArg(&fc->cdict, se);
01226
01227
01228 if (freeftype)
01229 ftype = _free(ftype);
01230
01231 }
01232
01233
01234 fc->fknown = 0;
01235 for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
01236 se = fcav[fc->ix];
01237 assert(se != NULL);
01238
01239 dav = argvSearch(fc->cdict, se, NULL);
01240 if (dav) {
01241 xx = argiAdd(&fc->fcdictx, (int)fc->ix, (dav - fc->cdict));
01242 fc->fknown++;
01243 } else {
01244 xx = argiAdd(&fc->fcdictx, (int)fc->ix, 0);
01245 fc->fwhite++;
01246 }
01247 }
01248
01249 fcav = argvFree(fcav);
01250
01251 mg = rpmmgFree(mg);
01252 rpmlog(RPMLOG_DEBUG,
01253 D_("categorized %d files into %d classes (using %s).\n"),
01254 fc->nfiles, argvCount(fc->cdict), magicfile);
01255 magicfile = _free(magicfile);
01256
01257 return RPMRC_OK;
01258 }
01259
01262 typedef struct DepMsg_s * DepMsg_t;
01263
01266 struct DepMsg_s {
01267
01268 const char * msg;
01269
01270 const char * argv[4];
01271 rpmTag ntag;
01272 rpmTag vtag;
01273 rpmTag ftag;
01274 int mask;
01275 int xor;
01276 };
01277
01280
01281
01282 static struct DepMsg_s depMsgs[] = {
01283 { "Provides", { "%{?__find_provides}", NULL, NULL, NULL },
01284 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
01285 0, -1 },
01286 { "Requires(interp)", { NULL, "interp", NULL, NULL },
01287 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
01288 _notpre(RPMSENSE_INTERP), 0 },
01289 { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL },
01290 -1, -1, RPMTAG_REQUIREFLAGS,
01291 _notpre(RPMSENSE_RPMLIB), 0 },
01292 { "Requires(verify)", { NULL, "verify", NULL, NULL },
01293 -1, -1, RPMTAG_REQUIREFLAGS,
01294 RPMSENSE_SCRIPT_VERIFY, 0 },
01295 { "Requires(pre)", { NULL, "pre", NULL, NULL },
01296 -1, -1, RPMTAG_REQUIREFLAGS,
01297 _notpre(RPMSENSE_SCRIPT_PRE), 0 },
01298 { "Requires(post)", { NULL, "post", NULL, NULL },
01299 -1, -1, RPMTAG_REQUIREFLAGS,
01300 _notpre(RPMSENSE_SCRIPT_POST), 0 },
01301 { "Requires(preun)", { NULL, "preun", NULL, NULL },
01302 -1, -1, RPMTAG_REQUIREFLAGS,
01303 _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
01304 { "Requires(postun)", { NULL, "postun", NULL, NULL },
01305 -1, -1, RPMTAG_REQUIREFLAGS,
01306 _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
01307 { "Requires", { "%{?__find_requires}", NULL, NULL, NULL },
01308 -1, -1, RPMTAG_REQUIREFLAGS,
01309 RPMSENSE_FIND_REQUIRES|RPMSENSE_TRIGGERIN|RPMSENSE_TRIGGERUN|RPMSENSE_TRIGGERPOSTUN|RPMSENSE_TRIGGERPREIN, 0 },
01310 { "Conflicts", { "%{?__find_conflicts}", NULL, NULL, NULL },
01311 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS,
01312 0, -1 },
01313 { "Obsoletes", { "%{?__find_obsoletes}", NULL, NULL, NULL },
01314 RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS,
01315 0, -1 },
01316 { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 }
01317 };
01318
01319
01320
01321 static DepMsg_t DepMsgs = depMsgs;
01322
01327 static void printDeps(Header h)
01328
01329
01330 {
01331 DepMsg_t dm;
01332 rpmds ds = NULL;
01333 int flags = 0x2;
01334 const char * DNEVR;
01335 evrFlags Flags;
01336 int bingo = 0;
01337
01338 for (dm = DepMsgs; dm->msg != NULL; dm++) {
01339 if ((int)dm->ntag != -1) {
01340 (void)rpmdsFree(ds);
01341 ds = NULL;
01342 ds = rpmdsNew(h, dm->ntag, flags);
01343 }
01344 if (dm->ftag == 0)
01345 continue;
01346
01347 ds = rpmdsInit(ds);
01348 if (ds == NULL)
01349 continue;
01350
01351 bingo = 0;
01352 while (rpmdsNext(ds) >= 0) {
01353
01354 Flags = rpmdsFlags(ds);
01355
01356 if (!((Flags & dm->mask) ^ dm->xor))
01357 continue;
01358 if (bingo == 0) {
01359 rpmlog(RPMLOG_NOTICE, "%s:", (dm->msg ? dm->msg : ""));
01360 bingo = 1;
01361 }
01362 if ((DNEVR = rpmdsDNEVR(ds)) == NULL)
01363 continue;
01364 rpmlog(RPMLOG_NOTICE, " %s", DNEVR+2);
01365 }
01366 if (bingo)
01367 rpmlog(RPMLOG_NOTICE, "\n");
01368 }
01369 (void)rpmdsFree(ds);
01370 ds = NULL;
01371 }
01372
01375 static rpmRC rpmfcGenerateDependsHelper(const Spec spec, Package pkg, rpmfi fi)
01376
01377
01378 {
01379 rpmiob iob_stdin;
01380 rpmiob iob_stdout;
01381 DepMsg_t dm;
01382 int failnonzero = 0;
01383 rpmRC rc = RPMRC_OK;
01384
01385
01386
01387
01388 iob_stdin = rpmiobNew(0);
01389 fi = rpmfiInit(fi, 0);
01390 if (fi != NULL)
01391 while (rpmfiNext(fi) >= 0)
01392 iob_stdin = rpmiobAppend(iob_stdin, rpmfiFN(fi), 1);
01393
01394 for (dm = DepMsgs; dm->msg != NULL; dm++) {
01395 rpmTag tag;
01396 rpmsenseFlags tagflags;
01397 char * s;
01398 int xx;
01399
01400 tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
01401 tagflags = 0;
01402 s = NULL;
01403
01404 switch(tag) {
01405 case RPMTAG_PROVIDEFLAGS:
01406 if (!pkg->autoProv)
01407 continue;
01408 failnonzero = 1;
01409 tagflags = RPMSENSE_FIND_PROVIDES;
01410 break;
01411 case RPMTAG_REQUIREFLAGS:
01412 if (!pkg->autoReq)
01413 continue;
01414 failnonzero = 0;
01415 tagflags = RPMSENSE_FIND_REQUIRES;
01416 break;
01417 default:
01418 continue;
01419 break;
01420 }
01421
01422 xx = rpmfcExec(dm->argv, iob_stdin, &iob_stdout, failnonzero);
01423 if (xx == -1)
01424 continue;
01425
01426 s = rpmExpand(dm->argv[0], NULL);
01427 rpmlog(RPMLOG_NOTICE, _("Finding %s: %s\n"), dm->msg,
01428 (s ? s : ""));
01429 s = _free(s);
01430
01431 if (iob_stdout == NULL) {
01432 rpmlog(RPMLOG_ERR, _("Failed to find %s:\n"), dm->msg);
01433 rc = RPMRC_FAIL;
01434 break;
01435 }
01436
01437
01438 if (spec->_parseRCPOT)
01439 rc = spec->_parseRCPOT(spec, pkg, rpmiobStr(iob_stdout), tag,
01440 0, tagflags);
01441 iob_stdout = rpmiobFree(iob_stdout);
01442
01443 if (rc) {
01444 rpmlog(RPMLOG_ERR, _("Failed to find %s:\n"), dm->msg);
01445 break;
01446 }
01447 }
01448
01449 iob_stdin = rpmiobFree(iob_stdin);
01450
01451 return rc;
01452 }
01453
01456
01457
01458 static struct DepMsg_s scriptMsgs[] = {
01459 { "Requires(pre)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
01460 RPMTAG_PREINPROG, RPMTAG_PREIN, RPMTAG_REQUIREFLAGS,
01461 RPMSENSE_SCRIPT_PRE, 0 },
01462 { "Requires(post)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
01463 RPMTAG_POSTINPROG, RPMTAG_POSTIN, RPMTAG_REQUIREFLAGS,
01464 RPMSENSE_SCRIPT_POST, 0 },
01465 { "Requires(preun)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
01466 RPMTAG_PREUNPROG, RPMTAG_PREUN, RPMTAG_REQUIREFLAGS,
01467 RPMSENSE_SCRIPT_PREUN, 0 },
01468 { "Requires(postun)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
01469 RPMTAG_POSTUNPROG, RPMTAG_POSTUN, RPMTAG_REQUIREFLAGS,
01470 RPMSENSE_SCRIPT_POSTUN, 0 },
01471 { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 }
01472 };
01473
01474
01475
01476 static DepMsg_t ScriptMsgs = scriptMsgs;
01477
01480 static int rpmfcGenerateScriptletDeps(const Spec spec, Package pkg)
01481
01482
01483 {
01484 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01485 rpmiob iob_stdin = rpmiobNew(0);
01486 rpmiob iob_stdout = NULL;
01487 DepMsg_t dm;
01488 int failnonzero = 0;
01489 int rc = 0;
01490 int xx;
01491
01492 for (dm = ScriptMsgs; dm->msg != NULL; dm++) {
01493 int tag, tagflags;
01494 char * s;
01495
01496 tag = dm->ftag;
01497 tagflags = RPMSENSE_FIND_REQUIRES | dm->mask;
01498
01499
01500 he->tag = dm->ntag;
01501 xx = headerGet(pkg->header, he, 0);
01502 if (!xx || he->p.str == NULL)
01503 continue;
01504 xx = strcmp(he->p.str, "/bin/sh") && strcmp(he->p.str, "/bin/bash");
01505 he->p.ptr = _free(he->p.ptr);
01506 if (xx)
01507 continue;
01508
01509
01510 he->tag = dm->vtag;
01511 xx = headerGet(pkg->header, he, 0);
01512 if (!xx || he->p.str == NULL)
01513 continue;
01514 iob_stdin = rpmiobEmpty(iob_stdin);
01515 iob_stdin = rpmiobAppend(iob_stdin, he->p.str, 1);
01516 iob_stdin = rpmiobRTrim(iob_stdin);
01517 he->p.ptr = _free(he->p.ptr);
01518
01519 xx = rpmfcExec(dm->argv, iob_stdin, &iob_stdout, failnonzero);
01520 if (xx == -1)
01521 continue;
01522
01523
01524 s = rpmiobStr(iob_stdout);
01525 if (s != NULL && *s != '\0') {
01526 char * se = s;
01527
01528 while ((se = strstr(se, "executable(/")) != NULL) {
01529
01530 se = stpcpy(se, " ");
01531 *se = '/';
01532
01533 se = strchr(se, ')');
01534 if (se == NULL)
01535 break;
01536 *se++ = ' ';
01537 }
01538 if (spec->_parseRCPOT)
01539 rc = spec->_parseRCPOT(spec, pkg, s, tag, 0, tagflags);
01540 }
01541 iob_stdout = rpmiobFree(iob_stdout);
01542
01543 }
01544
01545 iob_stdin = rpmiobFree(iob_stdin);
01546
01547 return rc;
01548 }
01549
01550 rpmRC rpmfcGenerateDepends(void * specp, void * pkgp)
01551 {
01552 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01553 const Spec spec = specp;
01554 Package pkg = pkgp;
01555 rpmfi fi = pkg->cpioList;
01556 rpmfc fc = NULL;
01557 rpmds ds;
01558 int flags = 0x2;
01559 ARGV_t av;
01560 rpmuint16_t * fmode;
01561 int ac = rpmfiFC(fi);
01562 char buf[BUFSIZ];
01563 const char * N;
01564 const char * EVR;
01565 int genConfigDeps, internaldeps;
01566 rpmRC rc = RPMRC_OK;
01567 int i;
01568 int xx;
01569
01570
01571 if (ac <= 0)
01572 return RPMRC_OK;
01573
01574
01575 if (! (pkg->autoReq || pkg->autoProv))
01576 return RPMRC_OK;
01577
01578
01579 internaldeps = rpmExpandNumeric("%{?_use_internal_dependency_generator}");
01580 if (internaldeps == 0) {
01581
01582 rc = rpmfcGenerateDependsHelper(spec, pkg, fi);
01583 printDeps(pkg->header);
01584 return rc;
01585 }
01586
01587
01588 if (internaldeps > 1)
01589 xx = rpmfcGenerateScriptletDeps(spec, pkg);
01590
01591
01592
01593 av = xcalloc(ac+1, sizeof(*av));
01594 fmode = xcalloc(ac+1, sizeof(*fmode));
01595
01596 genConfigDeps = 0;
01597 fi = rpmfiInit(fi, 0);
01598 if (fi != NULL)
01599 while ((i = rpmfiNext(fi)) >= 0) {
01600 rpmfileAttrs fileAttrs;
01601
01602
01603 fileAttrs = rpmfiFFlags(fi);
01604 genConfigDeps |= (fileAttrs & RPMFILE_CONFIG);
01605
01606 av[i] = xstrdup(rpmfiFN(fi));
01607 fmode[i] = rpmfiFMode(fi);
01608 }
01609 av[ac] = NULL;
01610
01611 fc = rpmfcNew();
01612 fc->skipProv = !pkg->autoProv;
01613 fc->skipReq = !pkg->autoReq;
01614 fc->tracked = 0;
01615
01616 { const char * buildRootURL;
01617 const char * buildRoot;
01618 buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
01619 (void) urlPath(buildRootURL, &buildRoot);
01620 if (buildRoot && !strcmp(buildRoot, "/")) buildRoot = NULL;
01621 fc->brlen = (buildRoot ? strlen(buildRoot) : 0);
01622 buildRootURL = _free(buildRootURL);
01623 }
01624
01625
01626 if (!fc->skipProv) {
01627 ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, flags);
01628 xx = rpmdsMerge(&fc->provides, ds);
01629 (void)rpmdsFree(ds);
01630 ds = NULL;
01631 he->tag = RPMTAG_PROVIDENAME;
01632 xx = headerDel(pkg->header, he, 0);
01633 he->tag = RPMTAG_PROVIDEVERSION;
01634 xx = headerDel(pkg->header, he, 0);
01635 he->tag = RPMTAG_PROVIDEFLAGS;
01636 xx = headerDel(pkg->header, he, 0);
01637
01638
01639 if (genConfigDeps) {
01640 N = rpmdsN(pkg->ds);
01641 assert(N != NULL);
01642 EVR = rpmdsEVR(pkg->ds);
01643 assert(EVR != NULL);
01644 sprintf(buf, "config(%s)", N);
01645 ds = rpmdsSingle(RPMTAG_PROVIDENAME, buf, EVR,
01646 (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
01647 xx = rpmdsMerge(&fc->provides, ds);
01648 (void)rpmdsFree(ds);
01649 ds = NULL;
01650 }
01651 }
01652
01653 if (!fc->skipReq) {
01654 ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, flags);
01655 xx = rpmdsMerge(&fc->requires, ds);
01656 (void)rpmdsFree(ds);
01657 ds = NULL;
01658 he->tag = RPMTAG_REQUIRENAME;
01659 xx = headerDel(pkg->header, he, 0);
01660 he->tag = RPMTAG_REQUIREVERSION;
01661 xx = headerDel(pkg->header, he, 0);
01662 he->tag = RPMTAG_REQUIREFLAGS;
01663 xx = headerDel(pkg->header, he, 0);
01664
01665
01666 if (genConfigDeps) {
01667 N = rpmdsN(pkg->ds);
01668 assert(N != NULL);
01669 EVR = rpmdsEVR(pkg->ds);
01670 assert(EVR != NULL);
01671 sprintf(buf, "config(%s)", N);
01672 ds = rpmdsSingle(RPMTAG_REQUIRENAME, buf, EVR,
01673 (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
01674 xx = rpmdsMerge(&fc->requires, ds);
01675 (void)rpmdsFree(ds);
01676 ds = NULL;
01677 }
01678 }
01679
01680
01681 xx = rpmfcClassify(fc, av, fmode);
01682
01683
01684 xx = rpmfcApply(fc);
01685
01686
01687 he->tag = RPMTAG_FILECOLORS;
01688 he->t = RPM_UINT32_TYPE;
01689 he->p.ui32p = argiData(fc->fcolor);
01690 he->c = argiCount(fc->fcolor);
01691 assert(ac == (int)he->c);
01692 if (he->p.ptr != NULL && he->c > 0) {
01693 rpmuint32_t * fcolors = he->p.ui32p;
01694
01695
01696 for (i = 0; i < (int)he->c; i++)
01697 fcolors[i] &= 0x0f;
01698
01699 xx = headerPut(pkg->header, he, 0);
01700 }
01701
01702
01703 he->tag = RPMTAG_CLASSDICT;
01704 he->t = RPM_STRING_ARRAY_TYPE;
01705 he->p.argv = argvData(fc->cdict);
01706 he->c = argvCount(fc->cdict);
01707 if (he->p.ptr != NULL && he->c > 0) {
01708 xx = headerPut(pkg->header, he, 0);
01709 }
01710
01711
01712 he->tag = RPMTAG_FILECLASS;
01713 he->t = RPM_UINT32_TYPE;
01714 he->p.ui32p = argiData(fc->fcdictx);
01715 he->c = argiCount(fc->fcdictx);
01716 assert(ac == (int)he->c);
01717 if (he->p.ptr != NULL && he->c > 0) {
01718 xx = headerPut(pkg->header, he, 0);
01719 }
01720
01721
01722 if (fc->provides != NULL && (he->c = rpmdsCount(fc->provides)) > 0
01723 && !fc->skipProv)
01724 {
01725 he->tag = RPMTAG_PROVIDENAME;
01726 he->t = RPM_STRING_ARRAY_TYPE;
01727 he->p.argv = fc->provides->N;
01728 xx = headerPut(pkg->header, he, 0);
01729
01730
01731
01732 he->tag = RPMTAG_PROVIDEVERSION;
01733 he->t = RPM_STRING_ARRAY_TYPE;
01734 he->p.argv = fc->provides->EVR;
01735 assert(he->p.ptr != NULL);
01736 xx = headerPut(pkg->header, he, 0);
01737
01738 he->tag = RPMTAG_PROVIDEFLAGS;
01739 he->t = RPM_UINT32_TYPE;
01740 he->p.ui32p = (rpmuint32_t *) fc->provides->Flags;
01741 assert(he->p.ptr != NULL);
01742 xx = headerPut(pkg->header, he, 0);
01743
01744 }
01745
01746
01747 if (fc->requires != NULL && (he->c = rpmdsCount(fc->requires)) > 0
01748 && !fc->skipReq)
01749 {
01750 he->tag = RPMTAG_REQUIRENAME;
01751 he->t = RPM_STRING_ARRAY_TYPE;
01752 he->p.argv = fc->requires->N;
01753 assert(he->p.ptr != NULL);
01754 xx = headerPut(pkg->header, he, 0);
01755
01756
01757
01758 he->tag = RPMTAG_REQUIREVERSION;
01759 he->t = RPM_STRING_ARRAY_TYPE;
01760 he->p.argv = fc->requires->EVR;
01761 assert(he->p.ptr != NULL);
01762 xx = headerPut(pkg->header, he, 0);
01763
01764 he->tag = RPMTAG_REQUIREFLAGS;
01765 he->t = RPM_UINT32_TYPE;
01766 he->p.ui32p = (rpmuint32_t *) fc->requires->Flags;
01767 assert(he->p.ptr != NULL);
01768 xx = headerPut(pkg->header, he, 0);
01769
01770 }
01771
01772
01773 he->tag = RPMTAG_DEPENDSDICT;
01774 he->t = RPM_UINT32_TYPE;
01775 he->p.ui32p = argiData(fc->ddictx);
01776 he->c = argiCount(fc->ddictx);
01777 if (he->p.ptr != NULL) {
01778 xx = headerPut(pkg->header, he, 0);
01779 }
01780
01781
01782 he->tag = RPMTAG_FILEDEPENDSX;
01783 he->t = RPM_UINT32_TYPE;
01784 he->p.ui32p = argiData(fc->fddictx);
01785 he->c = argiCount(fc->fddictx);
01786 assert(ac == (int)he->c);
01787 if (he->p.ptr != NULL) {
01788 xx = headerPut(pkg->header, he, 0);
01789 }
01790
01791 he->tag = RPMTAG_FILEDEPENDSN;
01792 he->t = RPM_UINT32_TYPE;
01793 he->p.ui32p = argiData(fc->fddictn);
01794 he->c = argiCount(fc->fddictn);
01795 assert(ac == (int)he->c);
01796 if (he->p.ptr != NULL) {
01797 xx = headerPut(pkg->header, he, 0);
01798 }
01799
01800 printDeps(pkg->header);
01801
01802 if (fc != NULL && _rpmfc_debug) {
01803 char msg[BUFSIZ];
01804 sprintf(msg, "final: files %u cdict[%d] %u%% ddictx[%d]", (unsigned int)fc->nfiles, argvCount(fc->cdict), (unsigned int)((100 * fc->fknown)/fc->nfiles), argiCount(fc->ddictx));
01805 rpmfcPrint(msg, fc, NULL);
01806 }
01807
01808
01809 fmode = _free(fmode);
01810 fc = rpmfcFree(fc);
01811 av = argvFree(av);
01812
01813 return rc;
01814 }
01815
01816
01817 static void rpmfcFini(void * _fc)
01818
01819 {
01820 rpmfc fc = _fc;
01821
01822 fc->fn = argvFree(fc->fn);
01823 fc->fcolor = argiFree(fc->fcolor);
01824 fc->fcdictx = argiFree(fc->fcdictx);
01825 fc->fddictx = argiFree(fc->fddictx);
01826 fc->fddictn = argiFree(fc->fddictn);
01827 fc->cdict = argvFree(fc->cdict);
01828 fc->ddict = argvFree(fc->ddict);
01829 fc->ddictx = argiFree(fc->ddictx);
01830
01831 (void)rpmdsFree(fc->provides);
01832 fc->provides = NULL;
01833 (void)rpmdsFree(fc->requires);
01834 fc->requires = NULL;
01835
01836 fc->iob_java = rpmiobFree(fc->iob_java);
01837 fc->iob_perl = rpmiobFree(fc->iob_perl);
01838 fc->iob_python = rpmiobFree(fc->iob_python);
01839 fc->iob_php = rpmiobFree(fc->iob_php);
01840 }
01841
01842
01843
01844 rpmioPool _rpmfcPool = NULL;
01845
01846 static rpmfc rpmfcGetPool( rpmioPool pool)
01847
01848
01849 {
01850 rpmfc fc;
01851
01852 if (_rpmfcPool == NULL) {
01853 _rpmfcPool = rpmioNewPool("fc", sizeof(*fc), -1, _rpmfc_debug,
01854 NULL, NULL, rpmfcFini);
01855 pool = _rpmfcPool;
01856 }
01857 return (rpmfc) rpmioGetPool(pool, sizeof(*fc));
01858 }
01859
01860 rpmfc rpmfcNew(void)
01861 {
01862 rpmfc fc = rpmfcGetPool(_rpmfcPool);
01863 return rpmfcLink(fc);
01864 }
01865