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