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