00001 #include "system.h"
00002
00003 #include <signal.h>
00004
00005 #include <rpmbuild.h>
00006 #include <argv.h>
00007 #include <rpmfc.h>
00008
00009 #define _RPMDS_INTERNAL
00010 #include <rpmds.h>
00011 #include <rpmfi.h>
00012
00013 #if HAVE_GELF_H
00014 #include <gelf.h>
00015 #endif
00016
00017 #include "debug.h"
00018
00019
00020
00021
00024 static int rpmfcExpandAppend( ARGV_t * argvp, const ARGV_t av)
00025
00026
00027
00028 {
00029 ARGV_t argv = *argvp;
00030 int argc = argvCount(argv);
00031 int ac = argvCount(av);
00032 int i;
00033
00034
00035 argv = xrealloc(argv, (argc + ac + 1) * sizeof(*argv));
00036
00037 for (i = 0; i < ac; i++)
00038 argv[argc + i] = rpmExpand(av[i], NULL);
00039 argv[argc + ac] = NULL;
00040 *argvp = argv;
00041 return 0;
00042 }
00043
00053
00054 static StringBuf getOutputFrom( const char * dir, ARGV_t argv,
00055 const char * writePtr, int writeBytesLeft,
00056 int failNonZero)
00057
00058
00059 {
00060 pid_t child, reaped;
00061 int toProg[2];
00062 int fromProg[2];
00063 int status;
00064 void *oldhandler;
00065 StringBuf readBuff;
00066 int done;
00067
00068
00069 oldhandler = signal(SIGPIPE, SIG_IGN);
00070
00071
00072 toProg[0] = toProg[1] = 0;
00073 (void) pipe(toProg);
00074 fromProg[0] = fromProg[1] = 0;
00075 (void) pipe(fromProg);
00076
00077 if (!(child = fork())) {
00078 (void) close(toProg[1]);
00079 (void) close(fromProg[0]);
00080
00081 (void) dup2(toProg[0], STDIN_FILENO);
00082 (void) dup2(fromProg[1], STDOUT_FILENO);
00083
00084 (void) close(toProg[0]);
00085 (void) close(fromProg[1]);
00086
00087 if (dir) {
00088 (void) chdir(dir);
00089 }
00090
00091 rpmMessage(RPMMESS_DEBUG, _("\texecv(%s) pid %d\n"),
00092 argv[0], (unsigned)getpid());
00093
00094 unsetenv("MALLOC_CHECK_");
00095
00096 #if defined(__GLIBC__)
00097
00101 {
00102 char* bypassVar = (char*) malloc(1024*sizeof(char));
00103 if (bypassVar != NULL)
00104 {
00105 snprintf(bypassVar,1024*sizeof(char), "__PASSTHROUGH_LD_ASSUME_KERNEL_%d", getppid());
00106 bypassVar[1023] = '\0';
00107 if (getenv(bypassVar) != NULL)
00108 {
00109 char* bypassVal = (char*) malloc(1024*sizeof(char));
00110 if (bypassVal != NULL)
00111 {
00112 rpmMessage(RPMMESS_DEBUG, _("Restoring LD_ASSUME_KERNEL for child scripts.\n"));
00113 snprintf(bypassVal, 1024*sizeof(char), "%s", getenv(bypassVar));
00114 unsetenv(bypassVar);
00115 snprintf(bypassVar, 1024*sizeof(char), "LD_ASSUME_KERNEL=%s", bypassVal);
00116 bypassVar[1023] = '\0';
00117 putenv(bypassVar);
00118 free(bypassVal);
00119 }
00120 else
00121 {
00122 free(bypassVar);
00123 }
00124 }
00125 }
00126 }
00127 #endif
00128
00129 (void) execvp(argv[0], (char *const *)argv);
00130
00131 rpmError(RPMERR_EXEC, _("Couldn't exec %s: %s\n"),
00132 argv[0], strerror(errno));
00133 _exit(RPMERR_EXEC);
00134 }
00135 if (child < 0) {
00136 rpmError(RPMERR_FORK, _("Couldn't fork %s: %s\n"),
00137 argv[0], strerror(errno));
00138 return NULL;
00139 }
00140
00141 (void) close(toProg[0]);
00142 (void) close(fromProg[1]);
00143
00144
00145 (void) fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
00146 (void) fcntl(toProg[1], F_SETFL, O_NONBLOCK);
00147
00148 readBuff = newStringBuf();
00149
00150 do {
00151 fd_set ibits, obits;
00152 struct timeval tv;
00153 int nfd, nbw, nbr;
00154 int rc;
00155
00156 done = 0;
00157 top:
00158 FD_ZERO(&ibits);
00159 FD_ZERO(&obits);
00160 if (fromProg[0] >= 0) {
00161 FD_SET(fromProg[0], &ibits);
00162 }
00163 if (toProg[1] >= 0) {
00164 FD_SET(toProg[1], &obits);
00165 }
00166
00167 tv.tv_sec = 0;
00168 tv.tv_usec = 10000;
00169 nfd = ((fromProg[0] > toProg[1]) ? fromProg[0] : toProg[1]);
00170 if ((rc = select(nfd, &ibits, &obits, NULL, &tv)) < 0) {
00171 if (errno == EINTR)
00172 goto top;
00173 break;
00174 }
00175
00176
00177 if (toProg[1] >= 0 && FD_ISSET(toProg[1], &obits)) {
00178 if (writePtr && writeBytesLeft > 0) {
00179 if ((nbw = write(toProg[1], writePtr,
00180 (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
00181 if (errno != EAGAIN) {
00182 perror("getOutputFrom()");
00183 exit(EXIT_FAILURE);
00184 }
00185 nbw = 0;
00186 }
00187 writeBytesLeft -= nbw;
00188 writePtr += nbw;
00189 } else if (toProg[1] >= 0) {
00190 (void) close(toProg[1]);
00191 toProg[1] = -1;
00192 }
00193 }
00194
00195
00196
00197 { char buf[BUFSIZ+1];
00198 while ((nbr = read(fromProg[0], buf, sizeof(buf)-1)) > 0) {
00199 buf[nbr] = '\0';
00200 appendStringBuf(readBuff, buf);
00201 }
00202 }
00203
00204
00205
00206 done = (nbr == 0 || (nbr < 0 && errno != EAGAIN));
00207
00208 } while (!done);
00209
00210
00211 if (toProg[1] >= 0)
00212 (void) close(toProg[1]);
00213 if (fromProg[0] >= 0)
00214 (void) close(fromProg[0]);
00215
00216 (void) signal(SIGPIPE, oldhandler);
00217
00218
00219
00220 reaped = waitpid(child, &status, 0);
00221 rpmMessage(RPMMESS_DEBUG, _("\twaitpid(%d) rc %d status %x\n"),
00222 (unsigned)child, (unsigned)reaped, status);
00223
00224 if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
00225 rpmError(RPMERR_EXEC, _("%s failed\n"), argv[0]);
00226 return NULL;
00227 }
00228 if (writeBytesLeft) {
00229 rpmError(RPMERR_EXEC, _("failed to write all data to %s\n"), argv[0]);
00230 return NULL;
00231 }
00232 return readBuff;
00233 }
00234
00235 int rpmfcExec(ARGV_t av, StringBuf sb_stdin, StringBuf * sb_stdoutp,
00236 int failnonzero)
00237 {
00238 const char * s = NULL;
00239 ARGV_t xav = NULL;
00240 ARGV_t pav = NULL;
00241 int pac = 0;
00242 int ec = -1;
00243 StringBuf sb = NULL;
00244 const char * buf_stdin = NULL;
00245 int buf_stdin_len = 0;
00246 int xx;
00247
00248 if (sb_stdoutp)
00249 *sb_stdoutp = NULL;
00250 if (!(av && *av))
00251 goto exit;
00252
00253
00254 s = rpmExpand(av[0], NULL);
00255 if (!(s && *s))
00256 goto exit;
00257
00258
00259 pac = 0;
00260 xx = poptParseArgvString(s, &pac, (const char ***)&pav);
00261 if (!(xx == 0 && pac > 0 && pav != NULL))
00262 goto exit;
00263
00264
00265 xav = NULL;
00266
00267 xx = argvAppend(&xav, pav);
00268 if (av[1])
00269 xx = rpmfcExpandAppend(&xav, av + 1);
00270
00271
00272 if (sb_stdin != NULL) {
00273 buf_stdin = getStringBuf(sb_stdin);
00274 buf_stdin_len = strlen(buf_stdin);
00275 }
00276
00277
00278 sb = getOutputFrom(NULL, xav, buf_stdin, buf_stdin_len, failnonzero);
00279
00280
00281 if (sb_stdoutp != NULL) {
00282 *sb_stdoutp = sb;
00283 sb = NULL;
00284 }
00285
00286
00287 ec = 0;
00288
00289 exit:
00290 sb = freeStringBuf(sb);
00291 xav = argvFree(xav);
00292 pav = _free(pav);
00293 s = _free(s);
00294 return ec;
00295 }
00296
00299 static int rpmfcSaveArg( ARGV_t * argvp, const char * key)
00300
00301
00302 {
00303 int rc = 0;
00304
00305 if (argvSearch(*argvp, key, NULL) == NULL) {
00306 rc = argvAdd(argvp, key);
00307 rc = argvSort(*argvp, NULL);
00308 }
00309 return rc;
00310 }
00311
00312 static char * rpmfcFileDep( char * buf, int ix,
00313 rpmds ds)
00314
00315
00316
00317 {
00318 int_32 tagN = rpmdsTagN(ds);
00319 char deptype = 'X';
00320
00321 buf[0] = '\0';
00322 switch (tagN) {
00323 case RPMTAG_PROVIDENAME:
00324 deptype = 'P';
00325 break;
00326 case RPMTAG_REQUIRENAME:
00327 deptype = 'R';
00328 break;
00329 }
00330
00331 if (ds != NULL)
00332 sprintf(buf, "%08d%c %s %s 0x%08x", ix, deptype,
00333 rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
00334
00335 return buf;
00336 };
00337
00345 static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char * nsdep)
00346
00347
00348 {
00349 const char * fn = fc->fn[fc->ix];
00350 char buf[BUFSIZ];
00351 StringBuf sb_stdout = NULL;
00352 StringBuf sb_stdin;
00353 const char *av[2];
00354 rpmds * depsp, ds;
00355 const char * N;
00356 const char * EVR;
00357 int_32 Flags, dsContext, tagN;
00358 ARGV_t pav;
00359 const char * s;
00360 int pac;
00361 int xx;
00362 int i;
00363
00364 switch (deptype) {
00365 default:
00366 return -1;
00367 break;
00368 case 'P':
00369 if (fc->skipProv)
00370 return 0;
00371 xx = snprintf(buf, sizeof(buf), "%%{?__%s_provides}", nsdep);
00372 depsp = &fc->provides;
00373 dsContext = RPMSENSE_FIND_PROVIDES;
00374 tagN = RPMTAG_PROVIDENAME;
00375 break;
00376 case 'R':
00377 if (fc->skipReq)
00378 return 0;
00379 xx = snprintf(buf, sizeof(buf), "%%{?__%s_requires}", nsdep);
00380 depsp = &fc->requires;
00381 dsContext = RPMSENSE_FIND_REQUIRES;
00382 tagN = RPMTAG_REQUIRENAME;
00383 break;
00384 }
00385 buf[sizeof(buf)-1] = '\0';
00386 av[0] = buf;
00387 av[1] = NULL;
00388
00389 sb_stdin = newStringBuf();
00390 appendLineStringBuf(sb_stdin, fn);
00391 sb_stdout = NULL;
00392
00393 xx = rpmfcExec(av, sb_stdin, &sb_stdout, 0);
00394
00395 sb_stdin = freeStringBuf(sb_stdin);
00396
00397 if (xx == 0 && sb_stdout != NULL) {
00398 pav = NULL;
00399 xx = argvSplit(&pav, getStringBuf(sb_stdout), " \t\n\r");
00400 pac = argvCount(pav);
00401 if (pav)
00402 for (i = 0; i < pac; i++) {
00403 N = pav[i];
00404 EVR = "";
00405 Flags = dsContext;
00406
00407 if (pav[i+1] && strchr("=<>", *pav[i+1])) {
00408 i++;
00409 for (s = pav[i]; *s; s++) {
00410 switch(*s) {
00411 default:
00412 assert(*s != '\0');
00413 break;
00414 case '=':
00415 Flags |= RPMSENSE_EQUAL;
00416 break;
00417 case '<':
00418 Flags |= RPMSENSE_LESS;
00419 break;
00420 case '>':
00421 Flags |= RPMSENSE_GREATER;
00422 break;
00423 }
00424 }
00425 i++;
00426 EVR = pav[i];
00427 assert(EVR != NULL);
00428 }
00429
00430
00431
00432
00433 if (!fc->tracked && deptype == 'P' && *EVR != '\0') {
00434 ds = rpmdsSingle(RPMTAG_REQUIRENAME,
00435 "rpmlib(VersionedDependencies)", "3.0.3-1",
00436 RPMSENSE_RPMLIB|(RPMSENSE_LESS|RPMSENSE_EQUAL));
00437 xx = rpmdsMerge(&fc->requires, ds);
00438 ds = rpmdsFree(ds);
00439 fc->tracked = 1;
00440 }
00441
00442 ds = rpmdsSingle(tagN, N, EVR, Flags);
00443
00444
00445 xx = rpmdsMerge(depsp, ds);
00446
00447
00448
00449 xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
00450
00451
00452 ds = rpmdsFree(ds);
00453 }
00454
00455 pav = argvFree(pav);
00456 }
00457 sb_stdout = freeStringBuf(sb_stdout);
00458
00459 return 0;
00460 }
00461
00464
00465 static struct rpmfcTokens_s rpmfcTokens[] = {
00466 { "directory", RPMFC_DIRECTORY|RPMFC_INCLUDE },
00467
00468 { " shared object", RPMFC_LIBRARY },
00469 { " executable", RPMFC_EXECUTABLE },
00470 { " statically linked", RPMFC_STATIC },
00471 { " not stripped", RPMFC_NOTSTRIPPED },
00472 { " archive", RPMFC_ARCHIVE },
00473
00474 { "ELF 32-bit", RPMFC_ELF32|RPMFC_INCLUDE },
00475 { "ELF 64-bit", RPMFC_ELF64|RPMFC_INCLUDE },
00476
00477 { " script", RPMFC_SCRIPT },
00478 { " text", RPMFC_TEXT },
00479 { " document", RPMFC_DOCUMENT },
00480
00481 { " compressed", RPMFC_COMPRESSED },
00482
00483 { "troff or preprocessor input", RPMFC_MANPAGE },
00484
00485 { "perl script text", RPMFC_PERL|RPMFC_INCLUDE },
00486 { "Perl5 module source text", RPMFC_PERL|RPMFC_MODULE|RPMFC_INCLUDE },
00487
00488 { "current ar archive", RPMFC_STATIC|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_INCLUDE },
00489
00490 { "Zip archive data", RPMFC_COMPRESSED|RPMFC_ARCHIVE|RPMFC_INCLUDE },
00491 { "tar archive", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00492 { "cpio archive", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00493 { "RPM v3", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00494
00495 { " image", RPMFC_IMAGE|RPMFC_INCLUDE },
00496 { " font", RPMFC_FONT|RPMFC_INCLUDE },
00497 { " Font", RPMFC_FONT|RPMFC_INCLUDE },
00498
00499 { " commands", RPMFC_SCRIPT|RPMFC_INCLUDE },
00500 { " script", RPMFC_SCRIPT|RPMFC_INCLUDE },
00501
00502 { "python compiled", RPMFC_WHITE|RPMFC_INCLUDE },
00503
00504 { "empty", RPMFC_WHITE|RPMFC_INCLUDE },
00505
00506 { "HTML", RPMFC_WHITE|RPMFC_INCLUDE },
00507 { "SGML", RPMFC_WHITE|RPMFC_INCLUDE },
00508 { "XML", RPMFC_WHITE|RPMFC_INCLUDE },
00509
00510 { " program text", RPMFC_WHITE|RPMFC_INCLUDE },
00511 { " source", RPMFC_WHITE|RPMFC_INCLUDE },
00512 { "GLS_BINARY_LSB_FIRST", RPMFC_WHITE|RPMFC_INCLUDE },
00513 { " DB ", RPMFC_WHITE|RPMFC_INCLUDE },
00514
00515 { "ASCII English text", RPMFC_WHITE|RPMFC_INCLUDE },
00516 { "ASCII text", RPMFC_WHITE|RPMFC_INCLUDE },
00517 { "ISO-8859 text", RPMFC_WHITE|RPMFC_INCLUDE },
00518
00519 { "symbolic link to", RPMFC_SYMLINK },
00520 { "socket", RPMFC_DEVICE },
00521 { "special", RPMFC_DEVICE },
00522
00523 { "ASCII", RPMFC_WHITE },
00524 { "ISO-8859", RPMFC_WHITE },
00525
00526 { "data", RPMFC_WHITE },
00527
00528 { "application", RPMFC_WHITE },
00529 { "boot", RPMFC_WHITE },
00530 { "catalog", RPMFC_WHITE },
00531 { "code", RPMFC_WHITE },
00532 { "file", RPMFC_WHITE },
00533 { "format", RPMFC_WHITE },
00534 { "message", RPMFC_WHITE },
00535 { "program", RPMFC_WHITE },
00536
00537 { "broken symbolic link to ", RPMFC_WHITE|RPMFC_ERROR },
00538 { "can't read", RPMFC_WHITE|RPMFC_ERROR },
00539 { "can't stat", RPMFC_WHITE|RPMFC_ERROR },
00540 { "executable, can't read", RPMFC_WHITE|RPMFC_ERROR },
00541 { "core file", RPMFC_WHITE|RPMFC_ERROR },
00542
00543 { NULL, RPMFC_BLACK }
00544 };
00545
00546 int rpmfcColoring(const char * fmstr)
00547 {
00548 rpmfcToken fct;
00549 int fcolor = RPMFC_BLACK;
00550
00551 for (fct = rpmfcTokens; fct->token != NULL; fct++) {
00552 if (strstr(fmstr, fct->token) == NULL)
00553 continue;
00554 fcolor |= fct->colors;
00555 if (fcolor & RPMFC_INCLUDE)
00556 return fcolor;
00557 }
00558 return fcolor;
00559 }
00560
00561 void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
00562 {
00563 int fcolor;
00564 int ndx;
00565 int cx;
00566 int dx;
00567 int fx;
00568
00569 int nprovides;
00570 int nrequires;
00571
00572 if (fp == NULL) fp = stderr;
00573
00574 if (msg)
00575 fprintf(fp, "===================================== %s\n", msg);
00576
00577 nprovides = rpmdsCount(fc->provides);
00578 nrequires = rpmdsCount(fc->requires);
00579
00580 if (fc)
00581 for (fx = 0; fx < fc->nfiles; fx++) {
00582 assert(fx < fc->fcdictx->nvals);
00583 cx = fc->fcdictx->vals[fx];
00584 assert(fx < fc->fcolor->nvals);
00585 fcolor = fc->fcolor->vals[fx];
00586
00587 fprintf(fp, "%3d %s", fx, fc->fn[fx]);
00588 if (fcolor != RPMFC_BLACK)
00589 fprintf(fp, "\t0x%x", fc->fcolor->vals[fx]);
00590 else
00591 fprintf(fp, "\t%s", fc->cdict[cx]);
00592 fprintf(fp, "\n");
00593
00594 if (fc->fddictx == NULL || fc->fddictn == NULL)
00595 continue;
00596
00597 assert(fx < fc->fddictx->nvals);
00598 dx = fc->fddictx->vals[fx];
00599 assert(fx < fc->fddictn->nvals);
00600 ndx = fc->fddictn->vals[fx];
00601
00602 while (ndx-- > 0) {
00603 const char * depval;
00604 unsigned char deptype;
00605 unsigned ix;
00606
00607 ix = fc->ddictx->vals[dx++];
00608 deptype = ((ix >> 24) & 0xff);
00609 ix &= 0x00ffffff;
00610 depval = NULL;
00611 switch (deptype) {
00612 default:
00613 assert(depval != NULL);
00614 break;
00615 case 'P':
00616 if (nprovides > 0) {
00617 assert(ix < nprovides);
00618 (void) rpmdsSetIx(fc->provides, ix-1);
00619 if (rpmdsNext(fc->provides) >= 0)
00620 depval = rpmdsDNEVR(fc->provides);
00621 }
00622 break;
00623 case 'R':
00624 if (nrequires > 0) {
00625 assert(ix < nrequires);
00626 (void) rpmdsSetIx(fc->requires, ix-1);
00627 if (rpmdsNext(fc->requires) >= 0)
00628 depval = rpmdsDNEVR(fc->requires);
00629 }
00630 break;
00631 }
00632 if (depval)
00633 fprintf(fp, "\t%s\n", depval);
00634 }
00635 }
00636 }
00637
00638 rpmfc rpmfcFree(rpmfc fc)
00639 {
00640 if (fc) {
00641 fc->fn = argvFree(fc->fn);
00642 fc->fcolor = argiFree(fc->fcolor);
00643 fc->fcdictx = argiFree(fc->fcdictx);
00644 fc->fddictx = argiFree(fc->fddictx);
00645 fc->fddictn = argiFree(fc->fddictn);
00646 fc->cdict = argvFree(fc->cdict);
00647 fc->ddict = argvFree(fc->ddict);
00648 fc->ddictx = argiFree(fc->ddictx);
00649
00650 fc->provides = rpmdsFree(fc->provides);
00651 fc->requires = rpmdsFree(fc->requires);
00652
00653 fc->sb_java = freeStringBuf(fc->sb_java);
00654 fc->sb_perl = freeStringBuf(fc->sb_perl);
00655 fc->sb_python = freeStringBuf(fc->sb_python);
00656
00657 }
00658 fc = _free(fc);
00659 return NULL;
00660 }
00661
00662 rpmfc rpmfcNew(void)
00663 {
00664 rpmfc fc = xcalloc(1, sizeof(*fc));
00665 return fc;
00666 }
00667
00673 static int rpmfcSCRIPT(rpmfc fc)
00674
00675
00676 {
00677 const char * fn = fc->fn[fc->ix];
00678 const char * bn;
00679 rpmds ds;
00680 char buf[BUFSIZ];
00681 FILE * fp;
00682 char * s, * se;
00683 int i;
00684 struct stat sb, * st = &sb;
00685 int is_executable;
00686 int xx;
00687
00688
00689 if (stat(fn, st) < 0)
00690 return -1;
00691 is_executable = (st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
00692
00693 fp = fopen(fn, "r");
00694 if (fp == NULL || ferror(fp)) {
00695 if (fp) (void) fclose(fp);
00696 return -1;
00697 }
00698
00699
00700
00701 for (i = 0; i < 10; i++) {
00702
00703 s = fgets(buf, sizeof(buf) - 1, fp);
00704 if (s == NULL || ferror(fp) || feof(fp))
00705 break;
00706 s[sizeof(buf)-1] = '\0';
00707 if (!(s[0] == '#' && s[1] == '!'))
00708 continue;
00709 s += 2;
00710
00711 while (*s && strchr(" \t\n\r", *s) != NULL)
00712 s++;
00713 if (*s == '\0')
00714 continue;
00715 if (*s != '/')
00716 continue;
00717
00718 for (se = s+1; *se; se++) {
00719 if (strchr(" \t\n\r", *se) != NULL)
00720 break;
00721 }
00722 *se = '\0';
00723 se++;
00724
00725 if (is_executable) {
00726
00727 ds = rpmdsSingle(RPMTAG_REQUIRENAME, s, "", RPMSENSE_FIND_REQUIRES);
00728 xx = rpmdsMerge(&fc->requires, ds);
00729
00730
00731 xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(se, fc->ix, ds));
00732
00733 ds = rpmdsFree(ds);
00734 }
00735
00736
00737 bn = basename(s);
00738 if (!strcmp(bn, "perl"))
00739 fc->fcolor->vals[fc->ix] |= RPMFC_PERL;
00740 else if (!strcmp(bn, "python"))
00741 fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
00742
00743 break;
00744 }
00745
00746
00747 (void) fclose(fp);
00748
00749 if (fc->fcolor->vals[fc->ix] & RPMFC_PERL) {
00750 if (fc->fcolor->vals[fc->ix] & RPMFC_MODULE)
00751 xx = rpmfcHelper(fc, 'P', "perl");
00752 if (is_executable || (fc->fcolor->vals[fc->ix] & RPMFC_MODULE))
00753 xx = rpmfcHelper(fc, 'R', "perl");
00754 }
00755 if (fc->fcolor->vals[fc->ix] & RPMFC_PYTHON) {
00756 xx = rpmfcHelper(fc, 'P', "python");
00757 if (is_executable)
00758 xx = rpmfcHelper(fc, 'R', "python");
00759 }
00760
00761 return 0;
00762 }
00763
00769 static int rpmfcELF(rpmfc fc)
00770
00771
00772 {
00773 #if HAVE_GELF_H && HAVE_LIBELF
00774 const char * fn = fc->fn[fc->ix];
00775 Elf * elf;
00776 Elf_Scn * scn;
00777 Elf_Data * data;
00778 GElf_Ehdr ehdr_mem, * ehdr;
00779 GElf_Shdr shdr_mem, * shdr;
00780 GElf_Verdef def_mem, * def;
00781 GElf_Verneed need_mem, * need;
00782 GElf_Dyn dyn_mem, * dyn;
00783 unsigned int auxoffset;
00784 unsigned int offset;
00785 int fdno;
00786 int cnt2;
00787 int cnt;
00788 char buf[BUFSIZ];
00789 const char * s;
00790 struct stat sb, * st = &sb;
00791 const char * soname = NULL;
00792 rpmds * depsp, ds;
00793 int_32 tagN, dsContext;
00794 char * t;
00795 int xx;
00796 int isElf64;
00797 int isDSO;
00798 int gotSONAME = 0;
00799 static int filter_GLIBC_PRIVATE = 0;
00800 static int oneshot = 0;
00801
00802 if (oneshot == 0) {
00803 oneshot = 1;
00804 filter_GLIBC_PRIVATE = rpmExpandNumeric("%{?_filter_GLIBC_PRIVATE}");
00805 }
00806
00807
00808 if (stat(fn, st) != 0)
00809 return(-1);
00810
00811 fdno = open(fn, O_RDONLY);
00812 if (fdno < 0)
00813 return fdno;
00814
00815 (void) elf_version(EV_CURRENT);
00816
00817
00818 elf = NULL;
00819 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
00820 || elf_kind(elf) != ELF_K_ELF
00821 || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
00822 || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
00823 goto exit;
00824
00825
00826 isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
00827 isDSO = ehdr->e_type == ET_DYN;
00828
00829
00830 scn = NULL;
00831 while ((scn = elf_nextscn(elf, scn)) != NULL) {
00832 shdr = gelf_getshdr(scn, &shdr_mem);
00833 if (shdr == NULL)
00834 break;
00835
00836 soname = _free(soname);
00837 switch (shdr->sh_type) {
00838 default:
00839 continue;
00840 break;
00841 case SHT_GNU_verdef:
00842 data = NULL;
00843 if (!fc->skipProv)
00844 while ((data = elf_getdata (scn, data)) != NULL) {
00845 offset = 0;
00846 for (cnt = shdr->sh_info; --cnt >= 0; ) {
00847
00848 def = gelf_getverdef (data, offset, &def_mem);
00849 if (def == NULL)
00850 break;
00851 auxoffset = offset + def->vd_aux;
00852 for (cnt2 = def->vd_cnt; --cnt2 >= 0; ) {
00853 GElf_Verdaux aux_mem, * aux;
00854
00855 aux = gelf_getverdaux (data, auxoffset, &aux_mem);
00856 if (aux == NULL)
00857 break;
00858
00859 s = elf_strptr(elf, shdr->sh_link, aux->vda_name);
00860 if (s == NULL)
00861 break;
00862 if (def->vd_flags & VER_FLG_BASE) {
00863 soname = _free(soname);
00864 soname = xstrdup(s);
00865 auxoffset += aux->vda_next;
00866 continue;
00867 } else
00868 if (soname != NULL
00869 && !(filter_GLIBC_PRIVATE != 0
00870 && !strcmp(s, "GLIBC_PRIVATE")))
00871 {
00872 buf[0] = '\0';
00873 t = buf;
00874 t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
00875
00876 #if !defined(__alpha__)
00877 if (isElf64)
00878 t = stpcpy(t, "(64bit)");
00879 #endif
00880 t++;
00881
00882
00883 ds = rpmdsSingle(RPMTAG_PROVIDES,
00884 buf, "", RPMSENSE_FIND_PROVIDES);
00885 xx = rpmdsMerge(&fc->provides, ds);
00886
00887
00888 xx = rpmfcSaveArg(&fc->ddict,
00889 rpmfcFileDep(t, fc->ix, ds));
00890
00891 ds = rpmdsFree(ds);
00892 }
00893 auxoffset += aux->vda_next;
00894 }
00895 offset += def->vd_next;
00896 }
00897 }
00898 break;
00899 case SHT_GNU_verneed:
00900 data = NULL;
00901
00902 if (!fc->skipReq && (st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
00903 while ((data = elf_getdata (scn, data)) != NULL) {
00904 offset = 0;
00905 for (cnt = shdr->sh_info; --cnt >= 0; ) {
00906 need = gelf_getverneed (data, offset, &need_mem);
00907 if (need == NULL)
00908 break;
00909
00910 s = elf_strptr(elf, shdr->sh_link, need->vn_file);
00911 if (s == NULL)
00912 break;
00913 soname = _free(soname);
00914 soname = xstrdup(s);
00915 auxoffset = offset + need->vn_aux;
00916 for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) {
00917 GElf_Vernaux aux_mem, * aux;
00918
00919 aux = gelf_getvernaux (data, auxoffset, &aux_mem);
00920 if (aux == NULL)
00921 break;
00922
00923 s = elf_strptr(elf, shdr->sh_link, aux->vna_name);
00924 if (s == NULL)
00925 break;
00926
00927
00928 if (soname != NULL
00929 && !(filter_GLIBC_PRIVATE != 0
00930 && !strcmp(s, "GLIBC_PRIVATE")))
00931 {
00932 buf[0] = '\0';
00933 t = buf;
00934 t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
00935
00936 #if !defined(__alpha__)
00937 if (isElf64)
00938 t = stpcpy(t, "(64bit)");
00939 #endif
00940 t++;
00941
00942
00943 ds = rpmdsSingle(RPMTAG_REQUIRENAME,
00944 buf, "", RPMSENSE_FIND_REQUIRES);
00945 xx = rpmdsMerge(&fc->requires, ds);
00946
00947
00948 xx = rpmfcSaveArg(&fc->ddict,
00949 rpmfcFileDep(t, fc->ix, ds));
00950 ds = rpmdsFree(ds);
00951 }
00952 auxoffset += aux->vna_next;
00953 }
00954 offset += need->vn_next;
00955 }
00956 }
00957 break;
00958 case SHT_DYNAMIC:
00959 data = NULL;
00960 while ((data = elf_getdata (scn, data)) != NULL) {
00961
00962 for (cnt = 0; cnt < (shdr->sh_size / shdr->sh_entsize); ++cnt) {
00963 dyn = gelf_getdyn (data, cnt, &dyn_mem);
00964 if (dyn == NULL)
00965 break;
00966 s = NULL;
00967 switch (dyn->d_tag) {
00968 default:
00969 continue;
00970 break;
00971 case DT_NEEDED:
00972
00973 if (fc->skipReq || !(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
00974 continue;
00975
00976 depsp = &fc->requires;
00977 tagN = RPMTAG_REQUIRENAME;
00978 dsContext = RPMSENSE_FIND_REQUIRES;
00979 s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
00980 assert(s != NULL);
00981 break;
00982 case DT_SONAME:
00983 gotSONAME = 1;
00984
00985 if (fc->skipProv)
00986 continue;
00987 depsp = &fc->provides;
00988 tagN = RPMTAG_PROVIDENAME;
00989 dsContext = RPMSENSE_FIND_PROVIDES;
00990 s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
00991 assert(s != NULL);
00992 break;
00993 }
00994 if (s == NULL)
00995 continue;
00996
00997 buf[0] = '\0';
00998 t = buf;
00999 t = stpcpy(t, s);
01000
01001 #if !defined(__alpha__)
01002 if (isElf64)
01003 t = stpcpy(t, "()(64bit)");
01004 #endif
01005 t++;
01006
01007
01008 ds = rpmdsSingle(tagN, buf, "", dsContext);
01009 xx = rpmdsMerge(depsp, ds);
01010
01011
01012 xx = rpmfcSaveArg(&fc->ddict,
01013 rpmfcFileDep(t, fc->ix, ds));
01014
01015 ds = rpmdsFree(ds);
01016 }
01017
01018 }
01019 break;
01020 }
01021 }
01022
01023
01024
01025 if (!fc->skipProv && isDSO && !gotSONAME) {
01026 depsp = &fc->provides;
01027 tagN = RPMTAG_PROVIDENAME;
01028 dsContext = RPMSENSE_FIND_PROVIDES;
01029
01030 s = strrchr(fn, '/');
01031 if (s)
01032 s++;
01033 else
01034 s = fn;
01035
01036
01037 buf[0] = '\0';
01038 t = buf;
01039
01040 t = stpcpy(t, s);
01041
01042
01043 #if !defined(__alpha__)
01044 if (isElf64)
01045 t = stpcpy(t, "()(64bit)");
01046 #endif
01047
01048 t++;
01049
01050
01051 ds = rpmdsSingle(tagN, buf, "", dsContext);
01052 xx = rpmdsMerge(depsp, ds);
01053
01054
01055
01056 xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(t, fc->ix, ds));
01057
01058
01059 ds = rpmdsFree(ds);
01060 }
01061
01062 exit:
01063 soname = _free(soname);
01064 if (elf) (void) elf_end(elf);
01065 xx = close(fdno);
01066 return 0;
01067 #else
01068 return -1;
01069 #endif
01070 }
01071
01072 typedef struct rpmfcApplyTbl_s {
01073 int (*func) (rpmfc fc);
01074 int colormask;
01075 } * rpmfcApplyTbl;
01076
01079
01080 static struct rpmfcApplyTbl_s rpmfcApplyTable[] = {
01081 { rpmfcELF, RPMFC_ELF },
01082 { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PERL) },
01083 { NULL, 0 }
01084 };
01085
01086 int rpmfcApply(rpmfc fc)
01087 {
01088 rpmfcApplyTbl fcat;
01089 const char * s;
01090 char * se;
01091 rpmds ds;
01092 const char * N;
01093 const char * EVR;
01094 int_32 Flags;
01095 unsigned char deptype;
01096 int nddict;
01097 int previx;
01098 unsigned int val;
01099 int dix;
01100 int ix;
01101 int i;
01102 int xx;
01103
01104
01105 for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) {
01106
01107 for (fcat = rpmfcApplyTable; fcat->func != NULL; fcat++) {
01108 if (!(fc->fcolor->vals[fc->ix] & fcat->colormask))
01109 continue;
01110 xx = (*fcat->func) (fc);
01111 }
01112 }
01113
01114
01115
01116 nddict = argvCount(fc->ddict);
01117 previx = -1;
01118 for (i = 0; i < nddict; i++) {
01119 s = fc->ddict[i];
01120
01121
01122 ix = strtol(s, &se, 10);
01123 assert(se != NULL);
01124 deptype = *se++;
01125 se++;
01126 N = se;
01127 while (*se && *se != ' ')
01128 se++;
01129 *se++ = '\0';
01130 EVR = se;
01131 while (*se && *se != ' ')
01132 se++;
01133 *se++ = '\0';
01134 Flags = strtol(se, NULL, 16);
01135
01136 dix = -1;
01137 switch (deptype) {
01138 default:
01139 break;
01140 case 'P':
01141 ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
01142 dix = rpmdsFind(fc->provides, ds);
01143 ds = rpmdsFree(ds);
01144 break;
01145 case 'R':
01146 ds = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags);
01147 dix = rpmdsFind(fc->requires, ds);
01148 ds = rpmdsFree(ds);
01149 break;
01150 }
01151
01152
01153 #if 0
01154 assert(dix >= 0);
01155 #else
01156 if (dix < 0)
01157 continue;
01158 #endif
01159
01160 val = (deptype << 24) | (dix & 0x00ffffff);
01161 xx = argiAdd(&fc->ddictx, -1, val);
01162
01163 if (previx != ix) {
01164 previx = ix;
01165 xx = argiAdd(&fc->fddictx, ix, argiCount(fc->ddictx)-1);
01166 }
01167 if (fc->fddictn && fc->fddictn->vals)
01168 fc->fddictn->vals[ix]++;
01169 }
01170
01171
01172 return 0;
01173 }
01174
01175 int rpmfcClassify(rpmfc fc, ARGV_t argv)
01176 {
01177 ARGV_t fcav = NULL;
01178 ARGV_t dav;
01179 const char * s, * se;
01180 size_t slen;
01181 int fcolor;
01182 int xx;
01183 fmagic fm = global_fmagic;
01184 int action = 0;
01185 int wid = 0;
01186
01187 if (fc == NULL || argv == NULL)
01188 return 0;
01189
01190 fc->nfiles = argvCount(argv);
01191
01192
01193 xx = argiAdd(&fc->fddictx, fc->nfiles-1, 0);
01194 xx = argiAdd(&fc->fddictn, fc->nfiles-1, 0);
01195
01196
01197 xx = argvAdd(&fc->cdict, "");
01198 xx = argvAdd(&fc->cdict, "directory");
01199
01200
01201 fm->magicfile = default_magicfile;
01202
01203
01204
01205 xx = fmagicSetup(fm, fm->magicfile, action);
01206 for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
01207 s = argv[fc->ix];
01208 assert(s != NULL);
01209 slen = strlen(s);
01210
01211 fm->obp = fm->obuf;
01212 *fm->obp = '\0';
01213 fm->nob = sizeof(fm->obuf);
01214 xx = fmagicProcess(fm, s, wid);
01215
01216
01217 if (slen >= sizeof(".pm") && !strcmp(s+slen-(sizeof(".pm")-1), ".pm"))
01218 strcpy(fm->obuf, "Perl5 module source text");
01219
01220 se = fm->obuf;
01221 rpmMessage(RPMMESS_DEBUG, "%s: %s\n", s, se);
01222
01223 xx = argvAdd(&fc->fn, s);
01224 xx = argvAdd(&fcav, se);
01225
01226
01227 fcolor = rpmfcColoring(se);
01228 xx = argiAdd(&fc->fcolor, fc->ix, fcolor);
01229
01230
01231 if (fcolor != RPMFC_WHITE && (fcolor & RPMFC_INCLUDE))
01232 xx = rpmfcSaveArg(&fc->cdict, se);
01233
01234 }
01235
01236
01237 fc->fknown = 0;
01238 for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
01239 se = fcav[fc->ix];
01240 assert(se != NULL);
01241
01242 dav = argvSearch(fc->cdict, se, NULL);
01243 if (dav) {
01244 xx = argiAdd(&fc->fcdictx, fc->ix, (dav - fc->cdict));
01245 fc->fknown++;
01246 } else {
01247 xx = argiAdd(&fc->fcdictx, fc->ix, 0);
01248 fc->fwhite++;
01249 }
01250 }
01251
01252 fcav = argvFree(fcav);
01253
01254
01255
01256 return 0;
01257 }
01258
01261 typedef struct DepMsg_s * DepMsg_t;
01262
01265 struct DepMsg_s {
01266
01267 const char * msg;
01268
01269 const char * argv[4];
01270 rpmTag ntag;
01271 rpmTag vtag;
01272 rpmTag ftag;
01273 int mask;
01274 int xor;
01275 };
01276
01279
01280 static struct DepMsg_s depMsgs[] = {
01281 { "Provides", { "%{?__find_provides}", NULL, NULL, NULL },
01282 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
01283 0, -1 },
01284 #ifdef DYING
01285 { "PreReq", { NULL, NULL, NULL, NULL },
01286 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
01287 RPMSENSE_PREREQ, 0 },
01288 { "Requires(interp)", { NULL, "interp", NULL, NULL },
01289 -1, -1, RPMTAG_REQUIREFLAGS,
01290 _notpre(RPMSENSE_INTERP), 0 },
01291 #else
01292 { "Requires(interp)", { NULL, "interp", NULL, NULL },
01293 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
01294 _notpre(RPMSENSE_INTERP), 0 },
01295 #endif
01296 { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL },
01297 -1, -1, RPMTAG_REQUIREFLAGS,
01298 _notpre(RPMSENSE_RPMLIB), 0 },
01299 { "Requires(verify)", { NULL, "verify", NULL, NULL },
01300 -1, -1, RPMTAG_REQUIREFLAGS,
01301 RPMSENSE_SCRIPT_VERIFY, 0 },
01302 { "Requires(pre)", { NULL, "pre", NULL, NULL },
01303 -1, -1, RPMTAG_REQUIREFLAGS,
01304 _notpre(RPMSENSE_SCRIPT_PRE), 0 },
01305 { "Requires(post)", { NULL, "post", NULL, NULL },
01306 -1, -1, RPMTAG_REQUIREFLAGS,
01307 _notpre(RPMSENSE_SCRIPT_POST), 0 },
01308 { "Requires(preun)", { NULL, "preun", NULL, NULL },
01309 -1, -1, RPMTAG_REQUIREFLAGS,
01310 _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
01311 { "Requires(postun)", { NULL, "postun", NULL, NULL },
01312 -1, -1, RPMTAG_REQUIREFLAGS,
01313 _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
01314 { "Requires", { "%{?__find_requires}", NULL, NULL, NULL },
01315 -1, -1, RPMTAG_REQUIREFLAGS,
01316 RPMSENSE_PREREQ, RPMSENSE_PREREQ },
01317 { "Conflicts", { "%{?__find_conflicts}", NULL, NULL, NULL },
01318 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS,
01319 0, -1 },
01320 { "Obsoletes", { "%{?__find_obsoletes}", NULL, NULL, NULL },
01321 RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS,
01322 0, -1 },
01323 { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 }
01324 };
01325
01326
01327 static DepMsg_t DepMsgs = depMsgs;
01328
01331 static void printDeps(Header h)
01332
01333 {
01334 DepMsg_t dm;
01335 rpmds ds = NULL;
01336 int scareMem = 0;
01337 const char * DNEVR;
01338 int_32 Flags;
01339 int bingo = 0;
01340
01341 for (dm = DepMsgs; dm->msg != NULL; dm++) {
01342 if (dm->ntag != -1) {
01343 ds = rpmdsFree(ds);
01344 ds = rpmdsNew(h, dm->ntag, scareMem);
01345 }
01346 if (dm->ftag == 0)
01347 continue;
01348
01349 ds = rpmdsInit(ds);
01350 if (ds == NULL)
01351 continue;
01352
01353 bingo = 0;
01354 while (rpmdsNext(ds) >= 0) {
01355
01356 Flags = rpmdsFlags(ds);
01357
01358 if (!((Flags & dm->mask) ^ dm->xor))
01359 continue;
01360 if (bingo == 0) {
01361 rpmMessage(RPMMESS_NORMAL, "%s:", (dm->msg ? dm->msg : ""));
01362 bingo = 1;
01363 }
01364 if ((DNEVR = rpmdsDNEVR(ds)) == NULL)
01365 continue;
01366 rpmMessage(RPMMESS_NORMAL, " %s", DNEVR+2);
01367 }
01368 if (bingo)
01369 rpmMessage(RPMMESS_NORMAL, "\n");
01370 }
01371 ds = rpmdsFree(ds);
01372 }
01373
01376 static int rpmfcGenerateDependsHelper(const Spec spec, Package pkg, rpmfi fi)
01377
01378
01379 {
01380 StringBuf sb_stdin;
01381 StringBuf sb_stdout;
01382 DepMsg_t dm;
01383 int failnonzero = 0;
01384 int rc = 0;
01385
01386
01387
01388
01389 sb_stdin = newStringBuf();
01390 fi = rpmfiInit(fi, 0);
01391 if (fi != NULL)
01392 while (rpmfiNext(fi) >= 0)
01393 appendLineStringBuf(sb_stdin, rpmfiFN(fi));
01394
01395 for (dm = DepMsgs; dm->msg != NULL; dm++) {
01396 int tag, 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
01423 xx = rpmfcExec(dm->argv, sb_stdin, &sb_stdout, failnonzero);
01424
01425 if (xx == -1)
01426 continue;
01427
01428 s = rpmExpand(dm->argv[0], NULL);
01429 rpmMessage(RPMMESS_NORMAL, _("Finding %s: %s\n"), dm->msg,
01430 (s ? s : ""));
01431 s = _free(s);
01432
01433 if (sb_stdout == NULL) {
01434 rc = RPMERR_EXEC;
01435 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
01436 break;
01437 }
01438
01439
01440 rc = parseRCPOT(spec, pkg, getStringBuf(sb_stdout), tag, 0, tagflags);
01441 sb_stdout = freeStringBuf(sb_stdout);
01442
01443 if (rc) {
01444 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
01445 break;
01446 }
01447 }
01448
01449 sb_stdin = freeStringBuf(sb_stdin);
01450
01451 return rc;
01452 }
01453
01454 int rpmfcGenerateDepends(const Spec spec, Package pkg)
01455 {
01456 rpmfi fi = pkg->cpioList;
01457 rpmfc fc = NULL;
01458 rpmds ds;
01459 int scareMem = 0;
01460 ARGV_t av;
01461 int ac = rpmfiFC(fi);
01462 const void ** p;
01463 char buf[BUFSIZ];
01464 const char * N;
01465 const char * EVR;
01466 int genConfigDeps;
01467 int c;
01468 int rc = 0;
01469 int xx;
01470
01471
01472 if (ac <= 0)
01473 return 0;
01474
01475
01476 if (! (pkg->autoReq || pkg->autoProv))
01477 return 0;
01478
01479
01480 if (!rpmExpandNumeric("%{?_use_internal_dependency_generator}")) {
01481
01482 rc = rpmfcGenerateDependsHelper(spec, pkg, fi);
01483 printDeps(pkg->header);
01484 return rc;
01485 }
01486
01487
01488 av = xcalloc(ac+1, sizeof(*av));
01489
01490
01491 genConfigDeps = 0;
01492 fi = rpmfiInit(fi, 0);
01493 if (fi != NULL)
01494 while ((c = rpmfiNext(fi)) >= 0) {
01495 rpmfileAttrs fileAttrs;
01496
01497
01498 fileAttrs = rpmfiFFlags(fi);
01499 genConfigDeps |= (fileAttrs & RPMFILE_CONFIG);
01500
01501 av[c] = xstrdup(rpmfiFN(fi));
01502 }
01503 av[ac] = NULL;
01504
01505
01506 fc = rpmfcNew();
01507 fc->skipProv = !pkg->autoProv;
01508 fc->skipReq = !pkg->autoReq;
01509 fc->tracked = 0;
01510
01511
01512 if (!fc->skipProv) {
01513 ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, scareMem);
01514 xx = rpmdsMerge(&fc->provides, ds);
01515 ds = rpmdsFree(ds);
01516 xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDENAME);
01517 xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDEVERSION);
01518 xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDEFLAGS);
01519
01520
01521 if (genConfigDeps) {
01522 N = rpmdsN(pkg->ds);
01523 assert(N != NULL);
01524 EVR = rpmdsEVR(pkg->ds);
01525 assert(EVR != NULL);
01526 sprintf(buf, "config(%s)", N);
01527 ds = rpmdsSingle(RPMTAG_PROVIDENAME, buf, EVR,
01528 (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
01529 xx = rpmdsMerge(&fc->provides, ds);
01530 ds = rpmdsFree(ds);
01531 }
01532 }
01533
01534 if (!fc->skipReq) {
01535 ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, scareMem);
01536 xx = rpmdsMerge(&fc->requires, ds);
01537 ds = rpmdsFree(ds);
01538 xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIRENAME);
01539 xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIREVERSION);
01540 xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIREFLAGS);
01541
01542
01543 if (genConfigDeps) {
01544 N = rpmdsN(pkg->ds);
01545 assert(N != NULL);
01546 EVR = rpmdsEVR(pkg->ds);
01547 assert(EVR != NULL);
01548 sprintf(buf, "config(%s)", N);
01549 ds = rpmdsSingle(RPMTAG_REQUIRENAME, buf, EVR,
01550 (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
01551 xx = rpmdsMerge(&fc->requires, ds);
01552 ds = rpmdsFree(ds);
01553 }
01554 }
01555
01556
01557 xx = rpmfcClassify(fc, av);
01558
01559
01560 xx = rpmfcApply(fc);
01561
01562
01563 p = (const void **) argiData(fc->fcolor);
01564 c = argiCount(fc->fcolor);
01565 assert(ac == c);
01566 if (p != NULL && c > 0) {
01567 int_32 * fcolors = (int_32 *)p;
01568 int i;
01569
01570
01571 for (i = 0; i < c; i++)
01572 fcolors[i] &= 0x0f;
01573 xx = headerAddEntry(pkg->header, RPMTAG_FILECOLORS, RPM_INT32_TYPE,
01574 p, c);
01575 }
01576
01577
01578 p = (const void **) argvData(fc->cdict);
01579 c = argvCount(fc->cdict);
01580 if (p != NULL && c > 0)
01581 xx = headerAddEntry(pkg->header, RPMTAG_CLASSDICT, RPM_STRING_ARRAY_TYPE,
01582 p, c);
01583
01584
01585 p = (const void **) argiData(fc->fcdictx);
01586 c = argiCount(fc->fcdictx);
01587 assert(ac == c);
01588 if (p != NULL && c > 0)
01589 xx = headerAddEntry(pkg->header, RPMTAG_FILECLASS, RPM_INT32_TYPE,
01590 p, c);
01591
01592
01593
01594 if (fc->provides != NULL && (c = rpmdsCount(fc->provides)) > 0 && !fc->skipProv) {
01595 p = (const void **) fc->provides->N;
01596 xx = headerAddEntry(pkg->header, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
01597 p, c);
01598
01599
01600 p = (const void **) fc->provides->EVR;
01601 assert(p != NULL);
01602 xx = headerAddEntry(pkg->header, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
01603 p, c);
01604 p = (const void **) fc->provides->Flags;
01605 assert(p != NULL);
01606 xx = headerAddEntry(pkg->header, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
01607 p, c);
01608
01609 }
01610
01611
01612
01613
01614 if (fc->requires != NULL && (c = rpmdsCount(fc->requires)) > 0 && !fc->skipReq) {
01615 p = (const void **) fc->requires->N;
01616 xx = headerAddEntry(pkg->header, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE,
01617 p, c);
01618
01619
01620 p = (const void **) fc->requires->EVR;
01621 assert(p != NULL);
01622 xx = headerAddEntry(pkg->header, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE,
01623 p, c);
01624 p = (const void **) fc->requires->Flags;
01625 assert(p != NULL);
01626 xx = headerAddEntry(pkg->header, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE,
01627 p, c);
01628
01629 }
01630
01631
01632
01633 p = (const void **) argiData(fc->ddictx);
01634 c = argiCount(fc->ddictx);
01635 if (p != NULL)
01636 xx = headerAddEntry(pkg->header, RPMTAG_DEPENDSDICT, RPM_INT32_TYPE,
01637 p, c);
01638
01639
01640 p = (const void **) argiData(fc->fddictx);
01641 c = argiCount(fc->fddictx);
01642 assert(ac == c);
01643 if (p != NULL)
01644 xx = headerAddEntry(pkg->header, RPMTAG_FILEDEPENDSX, RPM_INT32_TYPE,
01645 p, c);
01646
01647 p = (const void **) argiData(fc->fddictn);
01648 c = argiCount(fc->fddictn);
01649 assert(ac == c);
01650 if (p != NULL)
01651 xx = headerAddEntry(pkg->header, RPMTAG_FILEDEPENDSN, RPM_INT32_TYPE,
01652 p, c);
01653
01654 printDeps(pkg->header);
01655
01656 if (fc != NULL && _rpmfc_debug) {
01657 char msg[BUFSIZ];
01658 sprintf(msg, "final: files %d cdict[%d] %d%% ddictx[%d]", fc->nfiles, argvCount(fc->cdict), ((100 * fc->fknown)/fc->nfiles), argiCount(fc->ddictx));
01659 rpmfcPrint(msg, fc, NULL);
01660 }
01661
01662
01663 fc = rpmfcFree(fc);
01664 av = argvFree(av);
01665
01666 return rc;
01667 }