00001 #include "system.h"
00002
00003 #include <signal.h>
00004 #include <regex.h>
00005
00006 #include <rpmbuild.h>
00007 #include <argv.h>
00008 #include <rpmfc.h>
00009
00010 #define _RPMDS_INTERNAL
00011 #include <rpmds.h>
00012 #include <rpmfi.h>
00013 #include <rpmts.h>
00014 #include <rpmdb.h>
00015
00016 #if HAVE_GELF_H
00017 #include <gelf.h>
00018 #endif
00019
00020 #include "debug.h"
00021
00022
00023
00026 static int rpmfcExpandAppend( ARGV_t * argvp, const ARGV_t av)
00027
00028
00029
00030 {
00031 ARGV_t argv = *argvp;
00032 int argc = argvCount(argv);
00033 int ac = argvCount(av);
00034 int i;
00035
00036
00037 argv = xrealloc(argv, (argc + ac + 1) * sizeof(*argv));
00038
00039 for (i = 0; i < ac; i++)
00040 argv[argc + i] = rpmExpand(av[i], NULL);
00041 argv[argc + ac] = NULL;
00042 *argvp = argv;
00043 return 0;
00044 }
00045
00056
00057 static StringBuf getOutputFrom( const char * dir, ARGV_t argv,
00058 const char * writePtr, int writeBytesLeft,
00059 int failNonZero)
00060
00061
00062 {
00063 pid_t child, reaped;
00064 int toProg[2];
00065 int fromProg[2];
00066 int status;
00067 void *oldhandler;
00068 StringBuf readBuff;
00069 int done;
00070
00071
00072 oldhandler = signal(SIGPIPE, SIG_IGN);
00073
00074
00075 toProg[0] = toProg[1] = 0;
00076 (void) pipe(toProg);
00077 fromProg[0] = fromProg[1] = 0;
00078 (void) pipe(fromProg);
00079
00080 if (!(child = fork())) {
00081 (void) close(toProg[1]);
00082 (void) close(fromProg[0]);
00083
00084 (void) dup2(toProg[0], STDIN_FILENO);
00085 (void) dup2(fromProg[1], STDOUT_FILENO);
00086
00087 (void) close(toProg[0]);
00088 (void) close(fromProg[1]);
00089
00090 if (dir) {
00091 (void) chdir(dir);
00092 }
00093
00094 rpmMessage(RPMMESS_DEBUG, _("\texecv(%s) pid %d\n"),
00095 argv[0], (unsigned)getpid());
00096
00097 unsetenv("MALLOC_CHECK_");
00098 (void) execvp(argv[0], (char *const *)argv);
00099
00100 rpmError(RPMERR_EXEC, _("Couldn't exec %s: %s\n"),
00101 argv[0], strerror(errno));
00102 _exit(RPMERR_EXEC);
00103 }
00104 if (child < 0) {
00105 rpmError(RPMERR_FORK, _("Couldn't fork %s: %s\n"),
00106 argv[0], strerror(errno));
00107 return NULL;
00108 }
00109
00110 (void) close(toProg[0]);
00111 (void) close(fromProg[1]);
00112
00113
00114 (void) fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
00115 (void) fcntl(toProg[1], F_SETFL, O_NONBLOCK);
00116
00117 readBuff = newStringBuf();
00118
00119 do {
00120 fd_set ibits, obits;
00121 struct timeval tv;
00122 int nfd, nbw, nbr;
00123 int rc;
00124
00125 done = 0;
00126 top:
00127 FD_ZERO(&ibits);
00128 FD_ZERO(&obits);
00129 if (fromProg[0] >= 0) {
00130 FD_SET(fromProg[0], &ibits);
00131 }
00132 if (toProg[1] >= 0) {
00133 FD_SET(toProg[1], &obits);
00134 }
00135
00136 tv.tv_sec = 0;
00137 tv.tv_usec = 10000;
00138 nfd = ((fromProg[0] > toProg[1]) ? fromProg[0] : toProg[1]);
00139 if ((rc = select(nfd, &ibits, &obits, NULL, &tv)) < 0) {
00140 if (errno == EINTR)
00141 goto top;
00142 break;
00143 }
00144
00145
00146 if (toProg[1] >= 0 && FD_ISSET(toProg[1], &obits)) {
00147 if (writePtr && writeBytesLeft > 0) {
00148 if ((nbw = write(toProg[1], writePtr,
00149 (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
00150 if (errno != EAGAIN) {
00151 perror("getOutputFrom()");
00152 exit(EXIT_FAILURE);
00153 }
00154 nbw = 0;
00155 }
00156 writeBytesLeft -= nbw;
00157 writePtr += nbw;
00158 } else if (toProg[1] >= 0) {
00159 (void) close(toProg[1]);
00160 toProg[1] = -1;
00161 }
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
00175 done = (nbr == 0 || (nbr < 0 && errno != EAGAIN));
00176
00177 } while (!done);
00178
00179
00180 if (toProg[1] >= 0)
00181 (void) close(toProg[1]);
00182 if (fromProg[0] >= 0)
00183 (void) close(fromProg[0]);
00184
00185 (void) signal(SIGPIPE, oldhandler);
00186
00187
00188
00189 reaped = waitpid(child, &status, 0);
00190 rpmMessage(RPMMESS_DEBUG, _("\twaitpid(%d) rc %d status %x\n"),
00191 (unsigned)child, (unsigned)reaped, status);
00192
00193 if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
00194 rpmError(RPMERR_EXEC, _("%s failed\n"), argv[0]);
00195 return NULL;
00196 }
00197 if (writeBytesLeft) {
00198 rpmError(RPMERR_EXEC, _("failed to write all data to %s\n"), argv[0]);
00199 return NULL;
00200 }
00201 return readBuff;
00202 }
00203
00204 int rpmfcExec(ARGV_t av, StringBuf sb_stdin, StringBuf * sb_stdoutp,
00205 int failnonzero)
00206 {
00207 const char * s = NULL;
00208 ARGV_t xav = NULL;
00209 ARGV_t pav = NULL;
00210 int pac = 0;
00211 int ec = -1;
00212 StringBuf sb = NULL;
00213 const char * buf_stdin = NULL;
00214 int buf_stdin_len = 0;
00215 int xx;
00216
00217 if (sb_stdoutp)
00218 *sb_stdoutp = NULL;
00219 if (!(av && *av))
00220 goto exit;
00221
00222
00223 s = rpmExpand(av[0], NULL);
00224 if (!(s && *s))
00225 goto exit;
00226
00227
00228 pac = 0;
00229 xx = poptParseArgvString(s, &pac, (const char ***)&pav);
00230 if (!(xx == 0 && pac > 0 && pav != NULL))
00231 goto exit;
00232
00233
00234 xav = NULL;
00235
00236 xx = argvAppend(&xav, pav);
00237 if (av[1])
00238 xx = rpmfcExpandAppend(&xav, av + 1);
00239
00240
00241 if (sb_stdin != NULL) {
00242 buf_stdin = getStringBuf(sb_stdin);
00243 buf_stdin_len = strlen(buf_stdin);
00244 }
00245
00246
00247 sb = getOutputFrom(NULL, xav, buf_stdin, buf_stdin_len, failnonzero);
00248
00249
00250 if (sb_stdoutp != NULL) {
00251 *sb_stdoutp = sb;
00252 sb = NULL;
00253 }
00254
00255
00256 ec = 0;
00257
00258 exit:
00259 sb = freeStringBuf(sb);
00260 xav = argvFree(xav);
00261 pav = _free(pav);
00262 s = _free(s);
00263 return ec;
00264 }
00265
00268 static int rpmfcSaveArg( ARGV_t * argvp, const char * key)
00269
00270
00271 {
00272 int rc = 0;
00273
00274 if (argvSearch(*argvp, key, NULL) == NULL) {
00275 rc = argvAdd(argvp, key);
00276 rc = argvSort(*argvp, NULL);
00277 }
00278 return rc;
00279 }
00280
00281 static char * rpmfcFileDep( char * buf, int ix,
00282 rpmds ds)
00283
00284
00285
00286 {
00287 int_32 tagN = rpmdsTagN(ds);
00288 char deptype = 'X';
00289
00290 buf[0] = '\0';
00291 switch (tagN) {
00292 case RPMTAG_PROVIDENAME:
00293 deptype = 'P';
00294 break;
00295 case RPMTAG_REQUIRENAME:
00296 deptype = 'R';
00297 break;
00298 }
00299
00300 if (ds != NULL)
00301 sprintf(buf, "%08d%c %s %s 0x%08x", ix, deptype,
00302 rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
00303
00304 return buf;
00305 };
00306
00307 static regex_t * rpmfcExpandRegexps(const char * str,int *count){
00308 int i,j,r;
00309 const char *s;
00310 ARGV_t patterns=NULL;
00311 regex_t *compiled=NULL;
00312
00313 s=rpmExpand(str,NULL);
00314 if (s) {
00315 poptParseArgvString(s,count,(const char ***)&patterns);
00316 s = _free(s);
00317 }
00318 if (patterns==NULL){
00319 *count=0;
00320 return NULL;
00321 }
00322 if (*count==0){
00323 _free(patterns);
00324 return NULL;
00325 }
00326
00327 compiled=malloc(sizeof(regex_t)*(*count));
00328 j=0;
00329 for(i=0;i<*count;i++){
00330 r=regcomp(&compiled[j],patterns[i],REG_NOSUB);
00331 if (r==0) j++;
00332 else {
00333 rpmMessage(RPMMESS_NORMAL,
00334 _("Compilation of regular expresion '%s'"
00335 " (expanded from '%s') failed. Skipping it.\n"),
00336 patterns[i],str);
00337 }
00338 }
00339 patterns=_free(patterns);
00340 if (j==0) {
00341 compiled=_free(compiled);
00342 *count=0;
00343 return NULL;
00344 }
00345 *count=j;
00346 return compiled;
00347 }
00348
00349 static int rpmfcMatchRegexps(regex_t *regexps, int count, const char *str, char deptype)
00350 {
00351 int j;
00352 for(j = 0; j < count; j++) {
00353 rpmMessage(RPMMESS_DEBUG,
00354 _("Checking %c: '%s' against _noauto expr. #%i\n"), deptype, str, j);
00355 if (!regexec(®exps[j], str, 0, NULL, 0)) {
00356 rpmMessage(RPMMESS_NORMAL,
00357 _("Skipping %c: '%s' as it matches _noauto expr. #%i\n"), deptype, str, j);
00358 return 1;
00359 }
00360 }
00361 return 0;
00362 }
00363
00364 static regex_t * rpmfcFreeRegexps(regex_t *regexps,int count){
00365 int i;
00366
00367 if (regexps)
00368 for(i=0;i<count;i++)
00369 regfree(®exps[i]);
00370 return _free(regexps);
00371 }
00372
00382 static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char * nsdep,
00383 regex_t * noauto, int noauto_c)
00384
00385
00386 {
00387 const char * fn = fc->fn[fc->ix];
00388 char buf[BUFSIZ];
00389 StringBuf sb_stdout = NULL;
00390 StringBuf sb_stdin;
00391 const char *av[2];
00392 rpmds * depsp, ds;
00393 const char * N;
00394 const char * EVR;
00395 int_32 Flags, dsContext, tagN;
00396 ARGV_t pav;
00397 const char * s;
00398 int pac;
00399 int xx;
00400 int i;
00401
00402 switch (deptype) {
00403 default:
00404 return -1;
00405 break;
00406 case 'P':
00407 if (fc->skipProv)
00408 return 0;
00409 xx = snprintf(buf, sizeof(buf), "%%{?__%s_provides}", nsdep);
00410 depsp = &fc->provides;
00411 dsContext = RPMSENSE_FIND_PROVIDES;
00412 tagN = RPMTAG_PROVIDENAME;
00413 break;
00414 case 'R':
00415 if (fc->skipReq)
00416 return 0;
00417 xx = snprintf(buf, sizeof(buf), "%%{?__%s_requires}", nsdep);
00418 depsp = &fc->requires;
00419 dsContext = RPMSENSE_FIND_REQUIRES;
00420 tagN = RPMTAG_REQUIRENAME;
00421 break;
00422 }
00423 buf[sizeof(buf)-1] = '\0';
00424 av[0] = buf;
00425 av[1] = NULL;
00426
00427 sb_stdin = newStringBuf();
00428 appendLineStringBuf(sb_stdin, fn);
00429 sb_stdout = NULL;
00430
00431 xx = rpmfcExec(av, sb_stdin, &sb_stdout, 0);
00432
00433 sb_stdin = freeStringBuf(sb_stdin);
00434
00435 if (xx == 0 && sb_stdout != NULL) {
00436 pav = NULL;
00437 xx = argvSplit(&pav, getStringBuf(sb_stdout), " \t\n\r");
00438 pac = argvCount(pav);
00439 if (pav)
00440 for (i = 0; i < pac; i++) {
00441 N = pav[i];
00442 EVR = "";
00443 Flags = dsContext;
00444
00445 if (pav[i+1] && strchr("=<>", *pav[i+1])) {
00446 i++;
00447 for (s = pav[i]; *s; s++) {
00448 switch(*s) {
00449 default:
00450 assert(*s != '\0');
00451 break;
00452 case '=':
00453 Flags |= RPMSENSE_EQUAL;
00454 break;
00455 case '<':
00456 Flags |= RPMSENSE_LESS;
00457 break;
00458 case '>':
00459 Flags |= RPMSENSE_GREATER;
00460 break;
00461 }
00462 }
00463 i++;
00464 EVR = pav[i];
00465 assert(EVR != NULL);
00466 }
00467
00468
00469 if(rpmfcMatchRegexps(noauto, noauto_c, N, deptype))
00470 continue;
00471
00472
00473 if (!fc->tracked && deptype == 'P' && *EVR != '\0') {
00474 ds = rpmdsSingle(RPMTAG_REQUIRENAME,
00475 "rpmlib(VersionedDependencies)", "3.0.3-1",
00476 RPMSENSE_RPMLIB|(RPMSENSE_LESS|RPMSENSE_EQUAL));
00477 xx = rpmdsMerge(&fc->requires, ds);
00478 ds = rpmdsFree(ds);
00479 fc->tracked = 1;
00480 }
00481
00482 ds = rpmdsSingle(tagN, N, EVR, Flags);
00483
00484
00485 xx = rpmdsMerge(depsp, ds);
00486
00487
00488
00489 xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
00490
00491
00492 ds = rpmdsFree(ds);
00493 }
00494
00495 pav = argvFree(pav);
00496 }
00497 sb_stdout = freeStringBuf(sb_stdout);
00498
00499 return 0;
00500 }
00501
00504
00505 static struct rpmfcTokens_s rpmfcTokens[] = {
00506 { "directory", RPMFC_DIRECTORY|RPMFC_INCLUDE },
00507
00508 { " shared object", RPMFC_LIBRARY },
00509 { " executable", RPMFC_EXECUTABLE },
00510 { " statically linked", RPMFC_STATIC },
00511 { " not stripped", RPMFC_NOTSTRIPPED },
00512 { " archive", RPMFC_ARCHIVE },
00513
00514 { "ELF 32-bit", RPMFC_ELF32|RPMFC_INCLUDE },
00515 { "ELF 64-bit", RPMFC_ELF64|RPMFC_INCLUDE },
00516
00517 { " script", RPMFC_SCRIPT },
00518 { " text", RPMFC_TEXT },
00519 { " document", RPMFC_DOCUMENT },
00520
00521 { " compressed", RPMFC_COMPRESSED },
00522
00523 { "troff or preprocessor input", RPMFC_MANPAGE|RPMFC_INCLUDE },
00524 { "GNU Info", RPMFC_MANPAGE|RPMFC_INCLUDE },
00525
00526 { "perl script text", RPMFC_PERL|RPMFC_INCLUDE },
00527 { "Perl5 module source text", RPMFC_PERL|RPMFC_MODULE|RPMFC_INCLUDE },
00528
00529 { "PHP script text", RPMFC_PHP|RPMFC_INCLUDE },
00530
00531 { " /usr/bin/python", RPMFC_PYTHON|RPMFC_INCLUDE },
00532
00533
00534
00535 { "python ", RPMFC_PYTHON|RPMFC_INCLUDE },
00536
00537
00538 { "PE executable", RPMFC_MONO|RPMFC_INCLUDE },
00539 { "executable PE", RPMFC_MONO|RPMFC_INCLUDE },
00540
00541 { "current ar archive", RPMFC_STATIC|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_INCLUDE },
00542
00543 { "Zip archive data", RPMFC_COMPRESSED|RPMFC_ARCHIVE|RPMFC_INCLUDE },
00544 { "tar archive", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00545 { "cpio archive", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00546 { "RPM v3", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00547 { "RPM v4", RPMFC_ARCHIVE|RPMFC_INCLUDE },
00548
00549 { " image", RPMFC_IMAGE|RPMFC_INCLUDE },
00550 { " font", RPMFC_FONT|RPMFC_INCLUDE },
00551 { " Font", RPMFC_FONT|RPMFC_INCLUDE },
00552
00553 { " commands", RPMFC_SCRIPT|RPMFC_INCLUDE },
00554 { " script", RPMFC_SCRIPT|RPMFC_INCLUDE },
00555
00556 { "empty", RPMFC_WHITE|RPMFC_INCLUDE },
00557
00558 { "HTML", RPMFC_WHITE|RPMFC_INCLUDE },
00559 { "SGML", RPMFC_WHITE|RPMFC_INCLUDE },
00560 { "XML", RPMFC_WHITE|RPMFC_INCLUDE },
00561
00562 { " program text", RPMFC_WHITE|RPMFC_INCLUDE },
00563 { " source", RPMFC_WHITE|RPMFC_INCLUDE },
00564 { "GLS_BINARY_LSB_FIRST", RPMFC_WHITE|RPMFC_INCLUDE },
00565 { " DB ", RPMFC_WHITE|RPMFC_INCLUDE },
00566
00567 { "ASCII English text", RPMFC_WHITE|RPMFC_INCLUDE },
00568 { "ASCII text", RPMFC_WHITE|RPMFC_INCLUDE },
00569 { "ISO-8859 text", RPMFC_WHITE|RPMFC_INCLUDE },
00570
00571 { "symbolic link to", RPMFC_SYMLINK },
00572 { "socket", RPMFC_DEVICE },
00573 { "special", RPMFC_DEVICE },
00574
00575 { "ASCII", RPMFC_WHITE },
00576 { "ISO-8859", RPMFC_WHITE },
00577
00578 { "data", RPMFC_WHITE },
00579
00580 { "application", RPMFC_WHITE },
00581 { "boot", RPMFC_WHITE },
00582 { "catalog", RPMFC_WHITE },
00583 { "code", RPMFC_WHITE },
00584 { "file", RPMFC_WHITE },
00585 { "format", RPMFC_WHITE },
00586 { "message", RPMFC_WHITE },
00587 { "program", RPMFC_WHITE },
00588
00589 { "broken symbolic link to ", RPMFC_WHITE|RPMFC_ERROR },
00590 { "can't read", RPMFC_WHITE|RPMFC_ERROR },
00591 { "can't stat", RPMFC_WHITE|RPMFC_ERROR },
00592 { "executable, can't read", RPMFC_WHITE|RPMFC_ERROR },
00593 { "core file", RPMFC_WHITE|RPMFC_ERROR },
00594
00595 { NULL, RPMFC_BLACK }
00596 };
00597
00598 int rpmfcColoring(const char * fmstr)
00599 {
00600 rpmfcToken fct;
00601 int fcolor = RPMFC_BLACK;
00602
00603 for (fct = rpmfcTokens; fct->token != NULL; fct++) {
00604 if (strstr(fmstr, fct->token) == NULL)
00605 continue;
00606 fcolor |= fct->colors;
00607 if (fcolor & RPMFC_INCLUDE)
00608 return fcolor;
00609 }
00610 return fcolor;
00611 }
00612
00613 void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
00614 {
00615 int fcolor;
00616 int ndx;
00617 int cx;
00618 int dx;
00619 int fx;
00620
00621 int nprovides;
00622 int nrequires;
00623
00624 if (fp == NULL) fp = stderr;
00625
00626 if (msg)
00627 fprintf(fp, "===================================== %s\n", msg);
00628
00629 nprovides = rpmdsCount(fc->provides);
00630 nrequires = rpmdsCount(fc->requires);
00631
00632 if (fc)
00633 for (fx = 0; fx < fc->nfiles; fx++) {
00634 assert(fx < fc->fcdictx->nvals);
00635 cx = fc->fcdictx->vals[fx];
00636 assert(fx < fc->fcolor->nvals);
00637 fcolor = fc->fcolor->vals[fx];
00638
00639 fprintf(fp, "%3d %s", fx, fc->fn[fx]);
00640 if (fcolor != RPMFC_BLACK)
00641 fprintf(fp, "\t0x%x", fc->fcolor->vals[fx]);
00642 else
00643 fprintf(fp, "\t%s", fc->cdict[cx]);
00644 fprintf(fp, "\n");
00645
00646 if (fc->fddictx == NULL || fc->fddictn == NULL)
00647 continue;
00648
00649 assert(fx < fc->fddictx->nvals);
00650 dx = fc->fddictx->vals[fx];
00651 assert(fx < fc->fddictn->nvals);
00652 ndx = fc->fddictn->vals[fx];
00653
00654 while (ndx-- > 0) {
00655 const char * depval;
00656 unsigned char deptype;
00657 unsigned ix;
00658
00659 ix = fc->ddictx->vals[dx++];
00660 deptype = ((ix >> 24) & 0xff);
00661 ix &= 0x00ffffff;
00662 depval = NULL;
00663 switch (deptype) {
00664 default:
00665 assert(depval != NULL);
00666 break;
00667 case 'P':
00668 if (nprovides > 0) {
00669 assert(ix < nprovides);
00670 (void) rpmdsSetIx(fc->provides, ix-1);
00671 if (rpmdsNext(fc->provides) >= 0)
00672 depval = rpmdsDNEVR(fc->provides);
00673 }
00674 break;
00675 case 'R':
00676 if (nrequires > 0) {
00677 assert(ix < nrequires);
00678 (void) rpmdsSetIx(fc->requires, ix-1);
00679 if (rpmdsNext(fc->requires) >= 0)
00680 depval = rpmdsDNEVR(fc->requires);
00681 }
00682 break;
00683 }
00684 if (depval)
00685 fprintf(fp, "\t%s\n", depval);
00686 }
00687 }
00688 }
00689
00690 rpmfc rpmfcFree(rpmfc fc)
00691 {
00692 if (fc) {
00693 fc->fn = argvFree(fc->fn);
00694 fc->fcolor = argiFree(fc->fcolor);
00695 fc->fcdictx = argiFree(fc->fcdictx);
00696 fc->fddictx = argiFree(fc->fddictx);
00697 fc->fddictn = argiFree(fc->fddictn);
00698 fc->cdict = argvFree(fc->cdict);
00699 fc->ddict = argvFree(fc->ddict);
00700 fc->ddictx = argiFree(fc->ddictx);
00701
00702 fc->provides = rpmdsFree(fc->provides);
00703 fc->requires = rpmdsFree(fc->requires);
00704
00705 fc->sb_java = freeStringBuf(fc->sb_java);
00706 fc->sb_perl = freeStringBuf(fc->sb_perl);
00707 fc->sb_php = freeStringBuf(fc->sb_php);
00708 fc->sb_python = freeStringBuf(fc->sb_python);
00709
00710 }
00711 fc = _free(fc);
00712 return NULL;
00713 }
00714
00715 rpmfc rpmfcNew(void)
00716 {
00717 rpmfc fc = xcalloc(1, sizeof(*fc));
00718 return fc;
00719 }
00720
00732 static int rpmfcSCRIPT(rpmfc fc, int findprov, int findreq,
00733 regex_t *noautoprov, int noautoprov_c, regex_t *noautoreq, int noautoreq_c)
00734
00735
00736 {
00737 const char * fn = fc->fn[fc->ix];
00738 const char * bn;
00739 rpmds ds;
00740 char buf[BUFSIZ];
00741 FILE * fp;
00742 char * s, * se;
00743 int i;
00744 struct stat sb, * st = &sb;
00745 int is_executable;
00746 int xx;
00747
00748
00749 if (stat(fn, st) < 0)
00750 return -1;
00751 is_executable = (st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
00752
00753 fp = fopen(fn, "r");
00754 if (fp == NULL || ferror(fp)) {
00755 if (fp) (void) fclose(fp);
00756 return -1;
00757 }
00758
00759
00760
00761 for (i = 0; i < 10; i++) {
00762
00763 s = fgets(buf, sizeof(buf) - 1, fp);
00764 if (s == NULL || ferror(fp) || feof(fp))
00765 break;
00766 s[sizeof(buf)-1] = '\0';
00767 if (!(s[0] == '#' && s[1] == '!'))
00768 continue;
00769 s += 2;
00770
00771 while (*s && strchr(" \t\n\r", *s) != NULL)
00772 s++;
00773 if (*s == '\0')
00774 continue;
00775 if (*s != '/')
00776 continue;
00777
00778 for (se = s+1; *se; se++) {
00779 if (strchr(" \t\n\r", *se) != NULL)
00780 break;
00781 }
00782 *se = '\0';
00783 se++;
00784
00785 if (is_executable && findreq && !rpmfcMatchRegexps(noautoreq, noautoreq_c, s, 'R')) {
00786
00787 ds = rpmdsSingle(RPMTAG_REQUIRENAME, s, "", RPMSENSE_FIND_REQUIRES);
00788 xx = rpmdsMerge(&fc->requires, ds);
00789
00790
00791 xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(se, fc->ix, ds));
00792
00793 ds = rpmdsFree(ds);
00794 }
00795
00796
00797 bn = basename(s);
00798 if (!strcmp(bn, "perl"))
00799 fc->fcolor->vals[fc->ix] |= RPMFC_PERL;
00800 else if (!strncmp(bn, "python", sizeof("python")-1))
00801 fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
00802 else if (!strcmp(bn, "php"))
00803 fc->fcolor->vals[fc->ix] |= RPMFC_PHP;
00804
00805 break;
00806 }
00807
00808
00809 (void) fclose(fp);
00810
00811 if (fc->fcolor->vals[fc->ix] & RPMFC_PERL) {
00812 if (findprov && fc->fcolor->vals[fc->ix] & RPMFC_MODULE)
00813 xx = rpmfcHelper(fc, 'P', "perl", noautoprov, noautoprov_c);
00814 if (findreq && (is_executable || (fc->fcolor->vals[fc->ix] & RPMFC_MODULE)))
00815 xx = rpmfcHelper(fc, 'R', "perl", noautoreq, noautoreq_c);
00816 }
00817 if (fc->fcolor->vals[fc->ix] & RPMFC_PYTHON) {
00818 if (findprov)
00819 xx = rpmfcHelper(fc, 'P', "python", noautoprov, noautoprov_c);
00820 if (findreq)
00821 xx = rpmfcHelper(fc, 'R', "python", noautoreq, noautoreq_c);
00822 }
00823 if (fc->fcolor->vals[fc->ix] & RPMFC_PHP) {
00824 if (findprov)
00825 xx = rpmfcHelper(fc, 'P', "php", noautoprov, noautoprov_c);
00826 if (findreq)
00827 xx = rpmfcHelper(fc, 'R', "php", noautoreq, noautoreq_c);
00828 }
00829
00830 return 0;
00831 }
00832
00844 static int rpmfcMONO(rpmfc fc, int findprov, int findreq,
00845 regex_t *noautoprov, int noautoprov_c, regex_t *noautoreq, int noautoreq_c)
00846
00847
00848 {
00849 const char * fn = fc->fn[fc->ix];
00850 FILE * fp;
00851 int xx;
00852
00853 fp = fopen(fn, "r");
00854 if (fp == NULL || ferror(fp)) {
00855 if (fp) (void) fclose(fp);
00856 return -1;
00857 }
00858
00859 (void) fclose(fp);
00860
00861 if (findprov)
00862 xx = rpmfcHelper(fc, 'P', "mono", noautoprov, noautoprov_c);
00863 if (findreq)
00864 xx = rpmfcHelper(fc, 'R', "mono", noautoreq, noautoreq_c);
00865
00866 return 0;
00867 }
00868
00880 static int rpmfcELF(rpmfc fc, int findprov, int findreq,
00881 regex_t *noautoprov, int noautoprov_c, regex_t *noautoreq, int noautoreq_c)
00882
00883
00884 {
00885 #if HAVE_GELF_H && HAVE_LIBELF
00886 const char * fn = fc->fn[fc->ix];
00887 Elf * elf;
00888 Elf_Scn * scn;
00889 Elf_Data * data;
00890 GElf_Ehdr ehdr_mem, * ehdr;
00891 GElf_Shdr shdr_mem, * shdr;
00892 GElf_Verdef def_mem, * def;
00893 GElf_Verneed need_mem, * need;
00894 GElf_Dyn dyn_mem, * dyn;
00895 unsigned int auxoffset;
00896 unsigned int offset;
00897 int fdno;
00898 int cnt2;
00899 int cnt;
00900 char buf[BUFSIZ];
00901 const char * s;
00902 struct stat sb, * st = &sb;
00903 const char * soname = NULL;
00904 rpmds * depsp, ds;
00905 int_32 tagN, dsContext;
00906 char * t;
00907 int xx;
00908 int isElf64;
00909 int isDSO;
00910 int gotSONAME = 0;
00911 int gotDEBUG = 0;
00912 static int filter_GLIBC_PRIVATE = 0;
00913 static int oneshot = 0;
00914
00915 if (oneshot == 0) {
00916 oneshot = 1;
00917 filter_GLIBC_PRIVATE = rpmExpandNumeric("%{?_filter_GLIBC_PRIVATE}");
00918 }
00919
00920
00921 if (stat(fn, st) != 0)
00922 return(-1);
00923
00924 fdno = open(fn, O_RDONLY);
00925 if (fdno < 0)
00926 return fdno;
00927
00928 (void) elf_version(EV_CURRENT);
00929
00930
00931 elf = NULL;
00932 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
00933 || elf_kind(elf) != ELF_K_ELF
00934 || (ehdr = gelf_getehdr(elf, &ehdr_mem)) == NULL
00935 || !(ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC))
00936 goto exit;
00937
00938
00939 isElf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
00940 isDSO = ehdr->e_type == ET_DYN;
00941
00942
00943 scn = NULL;
00944 while ((scn = elf_nextscn(elf, scn)) != NULL) {
00945 shdr = gelf_getshdr(scn, &shdr_mem);
00946 if (shdr == NULL)
00947 break;
00948
00949 soname = _free(soname);
00950 switch (shdr->sh_type) {
00951 default:
00952 continue;
00953 break;
00954 case SHT_GNU_verdef:
00955 data = NULL;
00956 if (!fc->skipProv)
00957 while ((data = elf_getdata (scn, data)) != NULL) {
00958 offset = 0;
00959 for (cnt = shdr->sh_info; --cnt >= 0; ) {
00960
00961 def = gelf_getverdef (data, offset, &def_mem);
00962 if (def == NULL)
00963 break;
00964 auxoffset = offset + def->vd_aux;
00965 for (cnt2 = def->vd_cnt; --cnt2 >= 0; ) {
00966 GElf_Verdaux aux_mem, * aux;
00967
00968 aux = gelf_getverdaux (data, auxoffset, &aux_mem);
00969 if (aux == NULL)
00970 break;
00971
00972 s = elf_strptr(elf, shdr->sh_link, aux->vda_name);
00973 if (s == NULL)
00974 break;
00975 if (def->vd_flags & VER_FLG_BASE) {
00976 soname = _free(soname);
00977 soname = xstrdup(s);
00978 auxoffset += aux->vda_next;
00979 continue;
00980 } else
00981 if (soname != NULL
00982 && !(filter_GLIBC_PRIVATE != 0
00983 && !strcmp(s, "GLIBC_PRIVATE")))
00984 {
00985 int doauto;
00986
00987 buf[0] = '\0';
00988 t = buf;
00989 t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
00990
00991 doauto = findprov && !rpmfcMatchRegexps(noautoprov, noautoprov_c, buf, 'P');
00992 #if !defined(__alpha__)
00993 if (isElf64)
00994 t = stpcpy(t, "(64bit)");
00995 #endif
00996 t++;
00997
00998 if (doauto) {
00999
01000 ds = rpmdsSingle(RPMTAG_PROVIDES,
01001 buf, "", RPMSENSE_FIND_PROVIDES);
01002 xx = rpmdsMerge(&fc->provides, ds);
01003
01004
01005 xx = rpmfcSaveArg(&fc->ddict,
01006 rpmfcFileDep(t, fc->ix, ds));
01007
01008 ds = rpmdsFree(ds);
01009 }
01010 }
01011 auxoffset += aux->vda_next;
01012 }
01013 offset += def->vd_next;
01014 }
01015 }
01016 break;
01017 case SHT_GNU_verneed:
01018 data = NULL;
01019
01020 if (!fc->skipReq && (st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
01021 while ((data = elf_getdata (scn, data)) != NULL) {
01022 offset = 0;
01023 for (cnt = shdr->sh_info; --cnt >= 0; ) {
01024 need = gelf_getverneed (data, offset, &need_mem);
01025 if (need == NULL)
01026 break;
01027
01028 s = elf_strptr(elf, shdr->sh_link, need->vn_file);
01029 if (s == NULL)
01030 break;
01031 soname = _free(soname);
01032 soname = xstrdup(s);
01033 auxoffset = offset + need->vn_aux;
01034 for (cnt2 = need->vn_cnt; --cnt2 >= 0; ) {
01035 GElf_Vernaux aux_mem, * aux;
01036
01037 aux = gelf_getvernaux (data, auxoffset, &aux_mem);
01038 if (aux == NULL)
01039 break;
01040
01041 s = elf_strptr(elf, shdr->sh_link, aux->vna_name);
01042 if (s == NULL)
01043 break;
01044
01045
01046 if (soname != NULL
01047 && !(filter_GLIBC_PRIVATE != 0
01048 && !strcmp(s, "GLIBC_PRIVATE")))
01049 {
01050 int doauto;
01051
01052 buf[0] = '\0';
01053 t = buf;
01054 t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
01055
01056 doauto = findreq && !rpmfcMatchRegexps(noautoreq, noautoreq_c, buf, 'R');
01057 #if !defined(__alpha__)
01058 if (isElf64)
01059 t = stpcpy(t, "(64bit)");
01060 #endif
01061 t++;
01062
01063 if (doauto) {
01064
01065 ds = rpmdsSingle(RPMTAG_REQUIRENAME,
01066 buf, "", RPMSENSE_FIND_REQUIRES);
01067 xx = rpmdsMerge(&fc->requires, ds);
01068
01069
01070 xx = rpmfcSaveArg(&fc->ddict,
01071 rpmfcFileDep(t, fc->ix, ds));
01072 ds = rpmdsFree(ds);
01073 }
01074 }
01075 auxoffset += aux->vna_next;
01076 }
01077 offset += need->vn_next;
01078 }
01079 }
01080 break;
01081 case SHT_DYNAMIC:
01082 data = NULL;
01083 while ((data = elf_getdata (scn, data)) != NULL) {
01084
01085 for (cnt = 0; cnt < (shdr->sh_size / shdr->sh_entsize); ++cnt) {
01086 dyn = gelf_getdyn (data, cnt, &dyn_mem);
01087 if (dyn == NULL)
01088 break;
01089 s = NULL;
01090 switch (dyn->d_tag) {
01091 default:
01092 continue;
01093 break;
01094 case DT_DEBUG:
01095 gotDEBUG = 1;
01096 continue;
01097 case DT_NEEDED:
01098
01099 if (fc->skipReq || !(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
01100 continue;
01101 if (!findreq)
01102 continue;
01103
01104 depsp = &fc->requires;
01105 tagN = RPMTAG_REQUIRENAME;
01106 dsContext = RPMSENSE_FIND_REQUIRES;
01107 s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
01108 assert(s != NULL);
01109 if(rpmfcMatchRegexps(noautoreq, noautoreq_c, s, 'R'))
01110 continue;
01111 break;
01112 case DT_SONAME:
01113 gotSONAME = 1;
01114
01115 if (fc->skipProv)
01116 continue;
01117 if (!findprov) continue;
01118 depsp = &fc->provides;
01119 tagN = RPMTAG_PROVIDENAME;
01120 dsContext = RPMSENSE_FIND_PROVIDES;
01121 s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
01122 assert(s != NULL);
01123 if(rpmfcMatchRegexps(noautoprov, noautoprov_c, s, 'P'))
01124 continue;
01125 break;
01126 }
01127 if (s == NULL)
01128 continue;
01129
01130 buf[0] = '\0';
01131 t = buf;
01132 t = stpcpy(t, s);
01133
01134 #if !defined(__alpha__)
01135 if (isElf64)
01136 t = stpcpy(t, "()(64bit)");
01137 #endif
01138 t++;
01139
01140
01141 ds = rpmdsSingle(tagN, buf, "", dsContext);
01142 xx = rpmdsMerge(depsp, ds);
01143
01144
01145 xx = rpmfcSaveArg(&fc->ddict,
01146 rpmfcFileDep(t, fc->ix, ds));
01147
01148 ds = rpmdsFree(ds);
01149 }
01150
01151 }
01152 break;
01153 }
01154 }
01155
01156
01157
01158 if (findprov && !fc->skipProv && isDSO && !gotDEBUG && !gotSONAME) {
01159 depsp = &fc->provides;
01160 tagN = RPMTAG_PROVIDENAME;
01161 dsContext = RPMSENSE_FIND_PROVIDES;
01162
01163 s = strrchr(fn, '/');
01164 if (s)
01165 s++;
01166 else
01167 s = fn;
01168
01169
01170 buf[0] = '\0';
01171 t = buf;
01172
01173 t = stpcpy(t, s);
01174
01175
01176 if(!rpmfcMatchRegexps(noautoprov, noautoprov_c, buf, 'P')) {
01177
01178 #if !defined(__alpha__)
01179 if (isElf64)
01180 t = stpcpy(t, "()(64bit)");
01181 #endif
01182
01183 t++;
01184
01185
01186 ds = rpmdsSingle(tagN, buf, "", dsContext);
01187 xx = rpmdsMerge(depsp, ds);
01188
01189
01190
01191 xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(t, fc->ix, ds));
01192
01193
01194 ds = rpmdsFree(ds);
01195 }
01196 }
01197
01198 exit:
01199 soname = _free(soname);
01200 if (elf) (void) elf_end(elf);
01201 xx = close(fdno);
01202 return 0;
01203 #else
01204 return -1;
01205 #endif
01206 }
01207
01208 typedef struct rpmfcApplyTbl_s {
01209 int (*func) (rpmfc fc, int findprov, int findreq,
01210 regex_t *noautoprov, int noautoprov_c, regex_t *noautoreq, int noautoreq_c);
01211 int colormask;
01212 } * rpmfcApplyTbl;
01213
01216
01217 static struct rpmfcApplyTbl_s rpmfcApplyTable[] = {
01218 { rpmfcELF, RPMFC_ELF },
01219 { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PERL) },
01220 { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PYTHON) },
01221 { rpmfcSCRIPT, (RPMFC_SCRIPT|RPMFC_PHP) },
01222 { rpmfcMONO, RPMFC_MONO },
01223 { NULL, 0 }
01224 };
01225
01226 static int rpmfcFindRequiredPackages(rpmfc fc)
01227 {
01228 rpmts ts=NULL;
01229 const char * s;
01230 char * se;
01231 rpmds ds;
01232 const char * N;
01233 const char * EVR;
01234 int_32 Flags;
01235 unsigned char deptype;
01236 int nddict;
01237 int previx;
01238 int ix;
01239 int i;
01240 int j;
01241 int xx;
01242 int r;
01243 const char * hname;
01244 rpmdbMatchIterator it;
01245 Header hdr;
01246 regex_t *noautoreqdep;
01247 int noautoreqdep_c;
01248
01249 noautoreqdep=rpmfcExpandRegexps("%{__noautoreqdep}", &noautoreqdep_c);
01250
01251 ts = rpmtsCreate();
01252
01253 rpmMessage(RPMMESS_NORMAL, _("Searching for required packages....\n"));
01254
01255 nddict = argvCount(fc->ddict);
01256 previx = -1;
01257 for (i = 0; i < nddict; i++) {
01258 s = fc->ddict[i];
01259
01260
01261 ix = strtol(s, &se, 10);
01262 assert(se != NULL);
01263 deptype = *se++;
01264 se++;
01265 N = se;
01266 while (*se && *se != ' ')
01267 se++;
01268 *se++ = '\0';
01269 EVR = se;
01270 while (*se && *se != ' ')
01271 se++;
01272 *se++ = '\0';
01273 Flags = strtol(se, NULL, 16);
01274
01275 if (deptype!='R') continue;
01276
01277 rpmMessage(RPMMESS_DEBUG, _("#%i requires: %s,%s,%i\n"),ix,N,EVR,Flags);
01278 if (EVR && EVR[0]) {
01279 rpmMessage(RPMMESS_DEBUG, _("skipping #%i require\n"));
01280 continue;
01281 }
01282 for(j=0;j<noautoreqdep_c;j++)
01283 if (!regexec(&noautoreqdep[j],N,0,NULL,0)) {
01284 rpmMessage(RPMMESS_NORMAL,
01285 _("skipping %s requirement processing"
01286 " (matches noautoreqdep pattern #%i)\n"),N,j);
01287 break;
01288 }
01289 if (j<noautoreqdep_c) continue;
01290 if (N[0]=='/') {
01291 rpmMessage(RPMMESS_DEBUG, _("skipping #%i require (is file requirement)\n"));
01292 continue;
01293 }
01294 it=rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, N, 0);
01295 if (!it) {
01296 rpmMessage(RPMMESS_DEBUG, _("%s -> not found\n"),N);
01297 continue;
01298 }
01299 rpmMessage(RPMMESS_DEBUG, _("Iterator: %p\n"),it);
01300 if (rpmdbGetIteratorCount(it)>1) {
01301 rpmMessage(RPMMESS_DEBUG, _("%s -> multiple (skipping)\n"),N);
01302 rpmdbFreeIterator(it);
01303 continue;
01304 }
01305 hdr=rpmdbNextIterator(it);
01306 assert(hdr!=NULL);
01307 r=rpmHeaderGetEntry(hdr,RPMTAG_NAME,NULL,(void **)&hname, NULL);
01308 assert(r<2);
01309 if (!strcmp(hname,N)) {
01310 rpmMessage(RPMMESS_DEBUG, _("%s -> %s (skipping)\n"),N,hname);
01311 rpmdbFreeIterator(it);
01312 continue;
01313 }
01314
01315 rpmMessage(RPMMESS_DEBUG, "%s -> %s\n",N,hname);
01316
01317 ds = rpmdsSingle(RPMTAG_REQUIRENAME, hname, "", RPMSENSE_FIND_REQUIRES);
01318 xx = rpmdsMerge(&fc->requires, ds);
01319 ds = rpmdsFree(ds);
01320
01321 rpmdbFreeIterator(it);
01322 }
01323
01324 noautoreqdep=rpmfcFreeRegexps(noautoreqdep,noautoreqdep_c);
01325 ts = rpmtsFree(ts);
01326 return 0;
01327 }
01328
01329 int rpmfcApply(rpmfc fc)
01330 {
01331 rpmfcApplyTbl fcat;
01332 const char * s;
01333 char * se;
01334 rpmds ds;
01335 const char * N;
01336 const char * EVR;
01337 int_32 Flags;
01338 unsigned char deptype;
01339 int nddict;
01340 int previx;
01341 unsigned int val;
01342 int dix;
01343 int ix;
01344 int i;
01345 int xx;
01346 int j;
01347 int findprov;
01348 int findreq;
01349 regex_t *noautoprovfiles = NULL;
01350 int noautoprovfiles_c;
01351 regex_t *noautoreqfiles = NULL;
01352 int noautoreqfiles_c;
01353 regex_t *noautoprov = NULL;
01354 int noautoprov_c;
01355 regex_t *noautoreq = NULL;
01356 int noautoreq_c;
01357 const char *buildroot;
01358 int buildroot_l;
01359
01360 buildroot = rpmExpand("%{buildroot}",NULL);
01361 buildroot_l = strlen(buildroot);
01362
01363 noautoprovfiles = rpmfcExpandRegexps("%{__noautoprovfiles}", &noautoprovfiles_c);
01364 noautoreqfiles = rpmfcExpandRegexps("%{__noautoreqfiles}", &noautoreqfiles_c);
01365 noautoprov = rpmfcExpandRegexps("%{__noautoprov}", &noautoprov_c);
01366 noautoreq = rpmfcExpandRegexps("%{__noautoreq}", &noautoreq_c);
01367 rpmMessage(RPMMESS_DEBUG, _("%i _noautoprov patterns.\n"), noautoprov_c);
01368 rpmMessage(RPMMESS_DEBUG, _("%i _noautoreq patterns.\n"), noautoreq_c);
01369
01370
01371 for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) {
01372
01373
01374
01375 { const char *fn = strstr(fc->fn[fc->ix], "/usr/lib");
01376 if (fn) {
01377 fn += sizeof("/usr/lib")-1;
01378 if (fn[0] == '6' && fn[1] == '4')
01379 fn += 2;
01380 if (!strncmp(fn, "/python", sizeof("/python")-1))
01381 fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
01382 }
01383 }
01384
01385 if (fc->fcolor->vals[fc->ix])
01386 for (fcat = rpmfcApplyTable; fcat->func != NULL; fcat++) {
01387 if (!(fc->fcolor->vals[fc->ix] & fcat->colormask))
01388 continue;
01389 findprov = 1;
01390 findreq = 1;
01391 if (strncmp(fc->fn[fc->ix],buildroot,buildroot_l)==0) {
01392 for(j = 0; j < noautoprovfiles_c; j++) {
01393 if (!regexec(&noautoprovfiles[j],
01394 fc->fn[fc->ix] + buildroot_l, 0, NULL, 0)) {
01395 rpmMessage(RPMMESS_NORMAL,
01396 _("skipping %s provides detection"
01397 " (matches noautoprovfiles pattern #%i)\n"),
01398 fc->fn[fc->ix], j);
01399 findprov = 0;
01400 break;
01401 }
01402 }
01403 for(j = 0; j < noautoreqfiles_c; j++) {
01404 if (!regexec(&noautoreqfiles[j],
01405 fc->fn[fc->ix] + buildroot_l, 0, NULL, 0)) {
01406 rpmMessage(RPMMESS_NORMAL,
01407 _("skipping %s requires detection"
01408 " (matches noautoreqfiles pattern #%i)\n"),
01409 fc->fn[fc->ix], j);
01410 findreq = 0;
01411 break;
01412 }
01413 }
01414 }
01415 xx = (*fcat->func) (fc, findprov, findreq,
01416 noautoprov, noautoprov_c, noautoreq, noautoreq_c);
01417 }
01418 }
01419
01420 noautoprovfiles = rpmfcFreeRegexps(noautoprovfiles, noautoprovfiles_c);
01421 noautoreqfiles = rpmfcFreeRegexps(noautoreqfiles, noautoreqfiles_c);
01422 noautoprov = rpmfcFreeRegexps(noautoprov, noautoprov_c);
01423 noautoreq = rpmfcFreeRegexps(noautoreq, noautoreq_c);
01424 #ifdef AUTODEP_PKGNAMES
01425 rpmfcFindRequiredPackages(fc);
01426 #endif
01427
01428
01429 nddict = argvCount(fc->ddict);
01430 previx = -1;
01431 for (i = 0; i < nddict; i++) {
01432 s = fc->ddict[i];
01433
01434
01435 ix = strtol(s, &se, 10);
01436 assert(se != NULL);
01437 deptype = *se++;
01438 se++;
01439 N = se;
01440 while (*se && *se != ' ')
01441 se++;
01442 *se++ = '\0';
01443 EVR = se;
01444 while (*se && *se != ' ')
01445 se++;
01446 *se++ = '\0';
01447 Flags = strtol(se, NULL, 16);
01448
01449 dix = -1;
01450 switch (deptype) {
01451 default:
01452 break;
01453 case 'P':
01454 ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
01455 dix = rpmdsFind(fc->provides, ds);
01456 ds = rpmdsFree(ds);
01457 break;
01458 case 'R':
01459 ds = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags);
01460 dix = rpmdsFind(fc->requires, ds);
01461 ds = rpmdsFree(ds);
01462 break;
01463 }
01464
01465
01466 #if 0
01467 assert(dix >= 0);
01468 #else
01469 if (dix < 0)
01470 continue;
01471 #endif
01472
01473 val = (deptype << 24) | (dix & 0x00ffffff);
01474 xx = argiAdd(&fc->ddictx, -1, val);
01475
01476 if (previx != ix) {
01477 previx = ix;
01478 xx = argiAdd(&fc->fddictx, ix, argiCount(fc->ddictx)-1);
01479 }
01480 if (fc->fddictn && fc->fddictn->vals)
01481 fc->fddictn->vals[ix]++;
01482 }
01483
01484
01485 return 0;
01486 }
01487
01488 int rpmfcClassify(rpmfc fc, ARGV_t argv, int_16 * fmode)
01489 {
01490 ARGV_t fcav = NULL;
01491 ARGV_t dav;
01492 const char * s, * se;
01493 size_t slen;
01494 int fcolor;
01495 int xx;
01496
01497 static const char * magicfile = "/usr/share/file/magic";
01498 int msflags = MAGIC_CHECK;
01499 magic_t ms = NULL;
01500
01501 if (fc == NULL || argv == NULL)
01502 return 0;
01503
01504 fc->nfiles = argvCount(argv);
01505
01506
01507 xx = argiAdd(&fc->fddictx, fc->nfiles-1, 0);
01508 xx = argiAdd(&fc->fddictn, fc->nfiles-1, 0);
01509
01510
01511 xx = argvAdd(&fc->cdict, "");
01512 xx = argvAdd(&fc->cdict, "directory");
01513
01514 ms = magic_open(msflags);
01515 if (ms == NULL) {
01516 xx = RPMERR_EXEC;
01517 rpmError(xx, _("magic_open(0x%x) failed: %s\n"),
01518 msflags, strerror(errno));
01519 assert(ms != NULL);
01520 }
01521
01522 xx = magic_load(ms, magicfile);
01523 if (xx == -1) {
01524 xx = RPMERR_EXEC;
01525 rpmError(xx, _("magic_load(ms, \"%s\") failed: %s\n"),
01526 magicfile, magic_error(ms));
01527 assert(xx != -1);
01528 }
01529
01530 for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
01531 const char * ftype;
01532 int_16 mode = (fmode ? fmode[fc->ix] : 0);
01533 char dbuf[1024];
01534
01535 s = argv[fc->ix];
01536 assert(s != NULL);
01537 slen = strlen(s);
01538
01539 switch (mode & S_IFMT) {
01540 case S_IFCHR: ftype = "character special"; break;
01541 case S_IFBLK: ftype = "block special"; break;
01542 case S_IFIFO: ftype = "fifo (named pipe)"; break;
01543 case S_IFSOCK: ftype = "socket"; break;
01544 case S_IFDIR:
01545 case S_IFLNK:
01546 case S_IFREG:
01547 default:
01548
01549
01550 if (slen >= sizeof(".pm") && !strcmp(s+slen-(sizeof(".pm")-1), ".pm"))
01551 ftype = "Perl5 module source text";
01552
01553 else if (slen >= sizeof(".php") && !strcmp(s+slen-(sizeof(".php")-1), ".php"))
01554 ftype = "PHP script text";
01555
01556 else if (slen >= fc->brlen+sizeof("/dev/") && !strncmp(s+fc->brlen, "/dev/", sizeof("/dev/")-1))
01557 ftype = "";
01558 else
01559 ftype = magic_file(ms, s);
01560
01561 if (ftype == NULL) {
01562 xx = RPMERR_EXEC;
01563 rpmError(xx, _("magic_file(ms, \"%s\") failed: mode %06o %s\n"),
01564 s, mode, magic_error(ms));
01565 assert(ftype != NULL);
01566 }
01567 }
01568
01569
01570 se = ftype;
01571 rpmMessage(RPMMESS_DEBUG, "%s: %s\n", s, se);
01572
01573
01574 xx = argvAdd(&fc->fn, s);
01575
01576
01577 xx = argvAdd(&fcav, se);
01578
01579
01580 fcolor = rpmfcColoring(se);
01581 xx = argiAdd(&fc->fcolor, fc->ix, fcolor);
01582
01583
01584 if (fcolor != RPMFC_WHITE && (fcolor & RPMFC_INCLUDE))
01585 xx = rpmfcSaveArg(&fc->cdict, se);
01586
01587 }
01588
01589
01590 fc->fknown = 0;
01591 for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
01592 se = fcav[fc->ix];
01593 assert(se != NULL);
01594
01595 dav = argvSearch(fc->cdict, se, NULL);
01596 if (dav) {
01597 xx = argiAdd(&fc->fcdictx, fc->ix, (dav - fc->cdict));
01598 fc->fknown++;
01599 } else {
01600 xx = argiAdd(&fc->fcdictx, fc->ix, 0);
01601 fc->fwhite++;
01602 }
01603 }
01604
01605 fcav = argvFree(fcav);
01606
01607 if (ms != NULL)
01608 magic_close(ms);
01609
01610 return 0;
01611 }
01612
01615 typedef struct DepMsg_s * DepMsg_t;
01616
01619 struct DepMsg_s {
01620
01621 const char * msg;
01622
01623 const char * argv[4];
01624 rpmTag ntag;
01625 rpmTag vtag;
01626 rpmTag ftag;
01627 int mask;
01628 int xor;
01629 };
01630
01633
01634 static struct DepMsg_s depMsgs[] = {
01635 { "Provides", { "%{?__find_provides}", NULL, NULL, NULL },
01636 RPMTAG_PROVIDENAME, RPMTAG_PROVIDEVERSION, RPMTAG_PROVIDEFLAGS,
01637 0, -1 },
01638 { "Requires(interp)", { NULL, "interp", NULL, NULL },
01639 RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION, RPMTAG_REQUIREFLAGS,
01640 _notpre(RPMSENSE_INTERP), 0 },
01641 { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL },
01642 -1, -1, RPMTAG_REQUIREFLAGS,
01643 _notpre(RPMSENSE_RPMLIB), 0 },
01644 { "Requires(verify)", { NULL, "verify", NULL, NULL },
01645 -1, -1, RPMTAG_REQUIREFLAGS,
01646 RPMSENSE_SCRIPT_VERIFY, 0 },
01647 { "Requires(pre)", { NULL, "pre", NULL, NULL },
01648 -1, -1, RPMTAG_REQUIREFLAGS,
01649 _notpre(RPMSENSE_SCRIPT_PRE), 0 },
01650 { "Requires(post)", { NULL, "post", NULL, NULL },
01651 -1, -1, RPMTAG_REQUIREFLAGS,
01652 _notpre(RPMSENSE_SCRIPT_POST), 0 },
01653 { "Requires(preun)", { NULL, "preun", NULL, NULL },
01654 -1, -1, RPMTAG_REQUIREFLAGS,
01655 _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
01656 { "Requires(postun)", { NULL, "postun", NULL, NULL },
01657 -1, -1, RPMTAG_REQUIREFLAGS,
01658 _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
01659 { "Requires", { "%{?__find_requires}", NULL, NULL, NULL },
01660 -1, -1, RPMTAG_REQUIREFLAGS,
01661 RPMSENSE_FIND_REQUIRES|RPMSENSE_TRIGGERIN|RPMSENSE_TRIGGERUN|RPMSENSE_TRIGGERPOSTUN|RPMSENSE_TRIGGERPREIN, 0 },
01662 { "Conflicts", { "%{?__find_conflicts}", NULL, NULL, NULL },
01663 RPMTAG_CONFLICTNAME, RPMTAG_CONFLICTVERSION, RPMTAG_CONFLICTFLAGS,
01664 0, -1 },
01665 { "Obsoletes", { "%{?__find_obsoletes}", NULL, NULL, NULL },
01666 RPMTAG_OBSOLETENAME, RPMTAG_OBSOLETEVERSION, RPMTAG_OBSOLETEFLAGS,
01667 0, -1 },
01668 { NULL, { NULL, NULL, NULL, NULL }, 0, 0, 0, 0, 0 }
01669 };
01670
01671
01672 static DepMsg_t DepMsgs = depMsgs;
01673
01676 static void printDeps(Header h)
01677
01678
01679 {
01680 DepMsg_t dm;
01681 rpmds ds = NULL;
01682 int flags = 0x2;
01683 const char * DNEVR;
01684 int_32 Flags;
01685 int bingo = 0;
01686
01687 for (dm = DepMsgs; dm->msg != NULL; dm++) {
01688 if (dm->ntag != -1) {
01689 ds = rpmdsFree(ds);
01690 ds = rpmdsNew(h, dm->ntag, flags);
01691 }
01692 if (dm->ftag == 0)
01693 continue;
01694
01695 ds = rpmdsInit(ds);
01696 if (ds == NULL)
01697 continue;
01698
01699 bingo = 0;
01700 while (rpmdsNext(ds) >= 0) {
01701
01702 Flags = rpmdsFlags(ds);
01703
01704 if (!((Flags & dm->mask) ^ dm->xor))
01705 continue;
01706 if (bingo == 0) {
01707 rpmMessage(RPMMESS_NORMAL, "%s:", (dm->msg ? dm->msg : ""));
01708 bingo = 1;
01709 }
01710 if ((DNEVR = rpmdsDNEVR(ds)) == NULL)
01711 continue;
01712 rpmMessage(RPMMESS_NORMAL, " %s", DNEVR+2);
01713 }
01714 if (bingo)
01715 rpmMessage(RPMMESS_NORMAL, "\n");
01716 }
01717 ds = rpmdsFree(ds);
01718 }
01719
01722 static int rpmfcGenerateDependsHelper(const Spec spec, Package pkg, rpmfi fi)
01723
01724
01725 {
01726 StringBuf sb_stdin;
01727 StringBuf sb_stdout;
01728 DepMsg_t dm;
01729 int failnonzero = 0;
01730 int rc = 0;
01731
01732
01733
01734
01735 sb_stdin = newStringBuf();
01736 fi = rpmfiInit(fi, 0);
01737 if (fi != NULL)
01738 while (rpmfiNext(fi) >= 0)
01739 appendLineStringBuf(sb_stdin, rpmfiFN(fi));
01740
01741 for (dm = DepMsgs; dm->msg != NULL; dm++) {
01742 int tag, tagflags;
01743 char * s;
01744 int xx;
01745
01746 tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
01747 tagflags = 0;
01748 s = NULL;
01749
01750 switch(tag) {
01751 case RPMTAG_PROVIDEFLAGS:
01752 if (!pkg->autoProv)
01753 continue;
01754 failnonzero = 1;
01755 tagflags = RPMSENSE_FIND_PROVIDES;
01756 break;
01757 case RPMTAG_REQUIREFLAGS:
01758 if (!pkg->autoReq)
01759 continue;
01760 failnonzero = 0;
01761 tagflags = RPMSENSE_FIND_REQUIRES;
01762 break;
01763 default:
01764 continue;
01765 break;
01766 }
01767
01768
01769 xx = rpmfcExec(dm->argv, sb_stdin, &sb_stdout, failnonzero);
01770
01771 if (xx == -1)
01772 continue;
01773
01774 s = rpmExpand(dm->argv[0], NULL);
01775 rpmMessage(RPMMESS_NORMAL, _("Finding %s: %s\n"), dm->msg,
01776 (s ? s : ""));
01777 s = _free(s);
01778
01779 if (sb_stdout == NULL) {
01780 rc = RPMERR_EXEC;
01781 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
01782 break;
01783 }
01784
01785
01786 rc = parseRCPOT(spec, pkg, getStringBuf(sb_stdout), tag, 0, tagflags);
01787 sb_stdout = freeStringBuf(sb_stdout);
01788
01789 if (rc) {
01790 rpmError(rc, _("Failed to find %s:\n"), dm->msg);
01791 break;
01792 }
01793 }
01794
01795 sb_stdin = freeStringBuf(sb_stdin);
01796
01797 return rc;
01798 }
01799
01800 int rpmfcGenerateDepends(const Spec spec, Package pkg)
01801 {
01802 rpmfi fi = pkg->cpioList;
01803 rpmfc fc = NULL;
01804 rpmds ds;
01805 int flags = 0x2;
01806 ARGV_t av;
01807 int_16 * fmode;
01808 int ac = rpmfiFC(fi);
01809 const void ** p;
01810 char buf[BUFSIZ];
01811 const char * N;
01812 const char * EVR;
01813 int genConfigDeps;
01814 int c;
01815 int rc = 0;
01816 int xx;
01817
01818
01819 if (ac <= 0)
01820 return 0;
01821
01822
01823 if (! (pkg->autoReq || pkg->autoProv))
01824 return 0;
01825
01826
01827 if (!rpmExpandNumeric("%{?_use_internal_dependency_generator}")) {
01828
01829 rc = rpmfcGenerateDependsHelper(spec, pkg, fi);
01830 printDeps(pkg->header);
01831 return rc;
01832 }
01833
01834
01835 av = xcalloc(ac+1, sizeof(*av));
01836 fmode = xcalloc(ac+1, sizeof(*fmode));
01837
01838
01839 genConfigDeps = 0;
01840 fi = rpmfiInit(fi, 0);
01841 if (fi != NULL)
01842 while ((c = rpmfiNext(fi)) >= 0) {
01843 rpmfileAttrs fileAttrs;
01844
01845
01846 fileAttrs = rpmfiFFlags(fi);
01847 genConfigDeps |= (fileAttrs & RPMFILE_CONFIG);
01848
01849 av[c] = xstrdup(rpmfiFN(fi));
01850 fmode[c] = rpmfiFMode(fi);
01851 }
01852 av[ac] = NULL;
01853
01854
01855 fc = rpmfcNew();
01856 fc->skipProv = !pkg->autoProv;
01857 fc->skipReq = !pkg->autoReq;
01858 fc->tracked = 0;
01859 fc->brlen = (spec->buildRootURL ? strlen(spec->buildRootURL) : 0);
01860
01861
01862 if (!fc->skipProv) {
01863 ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, flags);
01864 xx = rpmdsMerge(&fc->provides, ds);
01865 ds = rpmdsFree(ds);
01866 xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDENAME);
01867 xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDEVERSION);
01868 xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDEFLAGS);
01869
01870
01871 if (genConfigDeps) {
01872 N = rpmdsN(pkg->ds);
01873 assert(N != NULL);
01874 EVR = rpmdsEVR(pkg->ds);
01875 assert(EVR != NULL);
01876 sprintf(buf, "config(%s)", N);
01877 ds = rpmdsSingle(RPMTAG_PROVIDENAME, buf, EVR,
01878 (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
01879 xx = rpmdsMerge(&fc->provides, ds);
01880 ds = rpmdsFree(ds);
01881 }
01882 }
01883
01884 if (!fc->skipReq) {
01885 ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, flags);
01886 xx = rpmdsMerge(&fc->requires, ds);
01887 ds = rpmdsFree(ds);
01888 xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIRENAME);
01889 xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIREVERSION);
01890 xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIREFLAGS);
01891
01892
01893 if (genConfigDeps) {
01894 N = rpmdsN(pkg->ds);
01895 assert(N != NULL);
01896 EVR = rpmdsEVR(pkg->ds);
01897 assert(EVR != NULL);
01898 sprintf(buf, "config(%s)", N);
01899 ds = rpmdsSingle(RPMTAG_REQUIRENAME, buf, EVR,
01900 (RPMSENSE_EQUAL|RPMSENSE_CONFIG));
01901 xx = rpmdsMerge(&fc->requires, ds);
01902 ds = rpmdsFree(ds);
01903 }
01904 }
01905
01906
01907 xx = rpmfcClassify(fc, av, fmode);
01908
01909
01910 xx = rpmfcApply(fc);
01911
01912
01913 p = (const void **) argiData(fc->fcolor);
01914 c = argiCount(fc->fcolor);
01915 assert(ac == c);
01916 if (p != NULL && c > 0) {
01917 int_32 * fcolors = (int_32 *)p;
01918 int i;
01919
01920
01921 for (i = 0; i < c; i++)
01922 fcolors[i] &= 0x0f;
01923 xx = headerAddEntry(pkg->header, RPMTAG_FILECOLORS, RPM_INT32_TYPE,
01924 p, c);
01925 }
01926
01927
01928 p = (const void **) argvData(fc->cdict);
01929 c = argvCount(fc->cdict);
01930 if (p != NULL && c > 0)
01931 xx = headerAddEntry(pkg->header, RPMTAG_CLASSDICT, RPM_STRING_ARRAY_TYPE,
01932 p, c);
01933
01934
01935 p = (const void **) argiData(fc->fcdictx);
01936 c = argiCount(fc->fcdictx);
01937 assert(ac == c);
01938 if (p != NULL && c > 0)
01939 xx = headerAddEntry(pkg->header, RPMTAG_FILECLASS, RPM_INT32_TYPE,
01940 p, c);
01941
01942
01943
01944 if (fc->provides != NULL && (c = rpmdsCount(fc->provides)) > 0 && !fc->skipProv) {
01945 p = (const void **) fc->provides->N;
01946 xx = headerAddEntry(pkg->header, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
01947 p, c);
01948
01949
01950 p = (const void **) fc->provides->EVR;
01951 assert(p != NULL);
01952 xx = headerAddEntry(pkg->header, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
01953 p, c);
01954 p = (const void **) fc->provides->Flags;
01955 assert(p != NULL);
01956 xx = headerAddEntry(pkg->header, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
01957 p, c);
01958
01959 }
01960
01961
01962
01963
01964 if (fc->requires != NULL && (c = rpmdsCount(fc->requires)) > 0 && !fc->skipReq) {
01965 p = (const void **) fc->requires->N;
01966 xx = headerAddEntry(pkg->header, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE,
01967 p, c);
01968
01969
01970 p = (const void **) fc->requires->EVR;
01971 assert(p != NULL);
01972 xx = headerAddEntry(pkg->header, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE,
01973 p, c);
01974 p = (const void **) fc->requires->Flags;
01975 assert(p != NULL);
01976 xx = headerAddEntry(pkg->header, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE,
01977 p, c);
01978
01979 }
01980
01981
01982
01983 p = (const void **) argiData(fc->ddictx);
01984 c = argiCount(fc->ddictx);
01985 if (p != NULL)
01986 xx = headerAddEntry(pkg->header, RPMTAG_DEPENDSDICT, RPM_INT32_TYPE,
01987 p, c);
01988
01989
01990 p = (const void **) argiData(fc->fddictx);
01991 c = argiCount(fc->fddictx);
01992 assert(ac == c);
01993 if (p != NULL)
01994 xx = headerAddEntry(pkg->header, RPMTAG_FILEDEPENDSX, RPM_INT32_TYPE,
01995 p, c);
01996
01997 p = (const void **) argiData(fc->fddictn);
01998 c = argiCount(fc->fddictn);
01999 assert(ac == c);
02000 if (p != NULL)
02001 xx = headerAddEntry(pkg->header, RPMTAG_FILEDEPENDSN, RPM_INT32_TYPE,
02002 p, c);
02003
02004 printDeps(pkg->header);
02005
02006 if (fc != NULL && _rpmfc_debug) {
02007 char msg[BUFSIZ];
02008 sprintf(msg, "final: files %d cdict[%d] %d%% ddictx[%d]", fc->nfiles, argvCount(fc->cdict), ((100 * fc->fknown)/fc->nfiles), argiCount(fc->ddictx));
02009 rpmfcPrint(msg, fc, NULL);
02010 }
02011
02012
02013 fmode = _free(fmode);
02014 fc = rpmfcFree(fc);
02015 av = argvFree(av);
02016
02017 return rc;
02018 }