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