rpm  5.4.15
rpmfc.c
Go to the documentation of this file.
1 #include "system.h"
2 
3 #include <signal.h> /* getOutputFrom() */
4 
5 #include <rpmio.h>
6 #include <rpmiotypes.h> /* XXX fnpyKey */
7 #include <rpmlog.h>
8 #include <rpmurl.h>
9 #include <rpmmg.h>
10 #include <argv.h>
11 #define _MIRE_INTERNAL
12 #include <mire.h>
13 
14 #include <rpmtag.h>
15 #define _RPMEVR_INTERNAL
16 #include <rpmbuild.h>
17 
18 #define _RPMNS_INTERNAL
19 #include <rpmns.h>
20 
21 #define _RPMFC_INTERNAL
22 #include <rpmfc.h>
23 
24 #define _RPMDS_INTERNAL
25 #include <rpmds.h>
26 #include <rpmfi.h>
27 
28 #include "debug.h"
29 
30 /*@access rpmds @*/
31 /*@access miRE @*/
32 
33 #ifdef __cplusplus
34 GENfree(rpmuint16_t *)
35 GENfree(rpmuint32_t *)
36 #endif /* __cplusplus */
37 
38 /*@unchecked@*/
39 static int _filter_values = 1;
40 /*@unchecked@*/
41 static int _filter_execs = 1;
42 
45 static int rpmfcExpandAppend(/*@out@*/ ARGV_t * argvp, const ARGV_t av)
46  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
47  /*@modifies *argvp, rpmGlobalMacroContext, internalState @*/
48  /*@requires maxRead(argvp) >= 0 @*/
49 {
50  ARGV_t argv = *argvp;
51  int argc = argvCount(argv);
52  int ac = argvCount(av);
53  int i;
54 
55  argv = (ARGV_t) xrealloc(argv, (argc + ac + 1) * sizeof(*argv));
56  for (i = 0; i < ac; i++)
57  argv[argc + i] = rpmExpand(av[i], NULL);
58  argv[argc + ac] = NULL;
59  *argvp = argv;
60  return 0;
61 }
62 
63 /* XXX FIXME: more AutoFu testing needed? */
64 #if defined(HAVE_SIG_T) && !defined(SIGHANDLER_T)
65 typedef sig_t sighandler_t;
66 #endif
67 
78 /*@null@*/
79 static rpmiob getOutputFrom(/*@null@*/ const char * dir, ARGV_t argv,
80  const char * writePtr, size_t writeBytesLeft,
81  int failNonZero)
82  /*@globals h_errno, fileSystem, internalState@*/
83  /*@modifies fileSystem, internalState@*/
84 {
85  pid_t child, reaped;
86  int toProg[2];
87  int fromProg[2];
88  int status;
89  sighandler_t oldhandler = signal(SIGPIPE, SIG_IGN);
90  rpmiob iob = NULL;
91  int done;
92 
93  toProg[0] = toProg[1] = 0;
94  fromProg[0] = fromProg[1] = 0;
95  if (pipe(toProg) < 0 || pipe(fromProg) < 0) {
96  rpmlog(RPMLOG_ERR, _("Couldn't create pipe for %s: %m\n"), argv[0]);
97  return NULL;
98  }
99 
100  if (!(child = fork())) {
101  (void) close(toProg[1]);
102  (void) close(fromProg[0]);
103 
104  (void) dup2(toProg[0], STDIN_FILENO); /* Make stdin the in pipe */
105  (void) dup2(fromProg[1], STDOUT_FILENO); /* Make stdout the out pipe */
106 
107  (void) close(toProg[0]);
108  (void) close(fromProg[1]);
109 
110  if (dir) {
111  (void) Chdir(dir);
112  }
113 
114  rpmlog(RPMLOG_DEBUG, D_("\texecv(%s) pid %d\n"),
115  argv[0], (unsigned)getpid());
116 
117  unsetenv("MALLOC_CHECK_");
118  (void) execvp(argv[0], (char *const *)argv);
119  /* XXX this error message is probably not seen. */
120  rpmlog(RPMLOG_ERR, _("Couldn't exec %s: %s\n"),
121  argv[0], strerror(errno));
122  _exit(EXIT_FAILURE);
123  }
124  if (child < 0) {
125  rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"),
126  argv[0], strerror(errno));
127  return NULL;
128  }
129 
130  (void) close(toProg[0]);
131  (void) close(fromProg[1]);
132 
133  /* Do not block reading or writing from/to prog. */
134  (void) fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
135  (void) fcntl(toProg[1], F_SETFL, O_NONBLOCK);
136 
137  iob = rpmiobNew(0);
138 
139  do {
140  fd_set ibits, obits;
141  struct timeval tv;
142  int nfd;
143  ssize_t nbr;
144  ssize_t nbw;
145  int rc;
146 
147  done = 0;
148 top:
149  FD_ZERO(&ibits);
150  FD_ZERO(&obits);
151  if (fromProg[0] >= 0) {
152  FD_SET(fromProg[0], &ibits);
153  }
154  if (toProg[1] >= 0) {
155  FD_SET(toProg[1], &obits);
156  }
157  /* XXX values set to limit spinning with perl doing ~100 forks/sec. */
158  tv.tv_sec = 0;
159  tv.tv_usec = 10000;
160  nfd = ((fromProg[0] > toProg[1]) ? fromProg[0] : toProg[1]);
161  if ((rc = select(nfd, &ibits, &obits, NULL, &tv)) < 0) {
162  if (errno == EINTR)
163  goto top;
164  break;
165  }
166 
167  /* Write any data to program */
168  if (toProg[1] >= 0 && FD_ISSET(toProg[1], &obits)) {
169  if (writePtr && writeBytesLeft > 0) {
170  if ((nbw = write(toProg[1], writePtr,
171  ((size_t)1024<writeBytesLeft) ? (size_t)1024 : writeBytesLeft)) < 0)
172  {
173  if (errno != EAGAIN) {
174  perror("getOutputFrom()");
175  exit(EXIT_FAILURE);
176  }
177  nbw = 0;
178  }
179  writeBytesLeft -= nbw;
180  writePtr += nbw;
181  } else if (toProg[1] >= 0) { /* close write fd */
182  (void) close(toProg[1]);
183  toProg[1] = -1;
184  }
185  }
186 
187  /* Read any data from prog */
188  { char buf[BUFSIZ+1];
189  while ((nbr = read(fromProg[0], buf, sizeof(buf)-1)) > 0) {
190  buf[nbr] = '\0';
191  iob = rpmiobAppend(iob, buf, 0);
192  }
193  }
194 
195  /* terminate on (non-blocking) EOF or error */
196  done = (nbr == 0 || (nbr < 0 && errno != EAGAIN));
197 
198  } while (!done);
199 
200  /* Clean up */
201  if (toProg[1] >= 0)
202  (void) close(toProg[1]);
203  if (fromProg[0] >= 0)
204  (void) close(fromProg[0]);
205  (void) signal(SIGPIPE, oldhandler);
206 
207  /* Collect status from prog */
208  reaped = waitpid(child, &status, 0);
209  rpmlog(RPMLOG_DEBUG, D_("\twaitpid(%d) rc %d status %x\n"),
210  (unsigned)child, (unsigned)reaped, status);
211 
212  if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
213  const char *cmd = argvJoin(argv, ' ');
214  int rc = (WIFEXITED(status) ? WEXITSTATUS(status) : -1);
215 
216  rpmlog(RPMLOG_ERR, _("Command \"%s\" failed, exit(%d)\n"), cmd, rc);
217  cmd = _free(cmd);
218  iob = rpmiobFree(iob);
219  return NULL;
220  }
221  if (writeBytesLeft) {
222  rpmlog(RPMLOG_ERR, _("failed to write all data to %s\n"), argv[0]);
223  iob = rpmiobFree(iob);
224  return NULL;
225  }
226  return iob;
227 }
228 
229 int rpmfcExec(ARGV_t av, rpmiob iob_stdin, rpmiob * iob_stdoutp,
230  int failnonzero)
231 {
232  const char * s = NULL;
233  ARGV_t xav = NULL;
234  ARGV_t pav = NULL;
235  int pac = 0;
236  int ec = -1;
237  rpmiob iob = NULL;
238  const char * buf_stdin = NULL;
239  size_t buf_stdin_len = 0;
240  int xx;
241 
242  if (iob_stdoutp)
243  *iob_stdoutp = NULL;
244  if (!(av && *av))
245  goto exit;
246 
247  /* Find path to executable with (possible) args. */
248  s = rpmExpand(av[0], NULL);
249  if (!(s && *s))
250  goto exit;
251 
252  /* Parse args buried within expanded executable. */
253  pac = 0;
254  xx = poptParseArgvString(s, &pac, (const char ***)&pav);
255  if (!(xx == 0 && pac > 0 && pav != NULL))
256  goto exit;
257 
258  /* Build argv, appending args to the executable args. */
259  xav = NULL;
260  xx = argvAppend(&xav, pav);
261  if (av[1])
262  xx = rpmfcExpandAppend(&xav, av + 1);
263 
264  if (iob_stdin != NULL) {
265  buf_stdin = rpmiobStr(iob_stdin);
266  buf_stdin_len = rpmiobLen(iob_stdin);
267  }
268 
269  /* Read output from exec'd helper. */
270  iob = getOutputFrom(NULL, xav, buf_stdin, buf_stdin_len, failnonzero);
271 
272  if (iob_stdoutp != NULL) {
273  *iob_stdoutp = iob;
274  iob = NULL; /* XXX don't free */
275  }
276 
277  ec = 0;
278 
279 exit:
280  iob = rpmiobFree(iob);
281  xav = argvFree(xav);
282  pav = _free(pav); /* XXX popt mallocs in single blob. */
283  s = _free(s);
284  return ec;
285 }
286 
289 static int rpmfcSaveArg(/*@out@*/ ARGV_t * argvp, const char * key)
290  /*@modifies *argvp @*/
291  /*@requires maxSet(argvp) >= 0 @*/
292 {
293  int rc = 0;
294 
295  if (argvSearch(*argvp, key, NULL) == NULL) {
296  rc = argvAdd(argvp, key);
297  rc = argvSort(*argvp, NULL);
298  }
299  return rc;
300 }
301 
304 static char * rpmfcFileDep(/*@returned@*/ char * buf, size_t ix,
305  /*@null@*/ rpmds ds)
306  /*@globals internalState @*/
307  /*@modifies buf, internalState @*/
308  /*@requires maxSet(buf) >= 0 @*/
309 {
310  rpmTag tagN = rpmdsTagN(ds);
311  char deptype = 'X';
312 
313  buf[0] = '\0';
314  switch (tagN) {
315  default:
316 assert(0);
317  /*@notreached@*/ break;
318  case RPMTAG_PROVIDENAME:
319  deptype = 'P';
320  break;
321  case RPMTAG_REQUIRENAME:
322  deptype = 'R';
323  break;
324  }
325 /*@-nullpass@*/
326  if (ds != NULL)
327  sprintf(buf, "%08u%c %s %s 0x%08x", (unsigned)ix, deptype,
328  rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
329 /*@=nullpass@*/
330  return buf;
331 };
332 
333 /*@null@*/
334 static void * rpmfcExpandRegexps(const char * str, int * nmirep)
335  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
336  /*@modifies *nmirep, rpmGlobalMacroContext, internalState @*/
337 {
338  ARGV_t av = NULL;
339  int ac = 0;
340  miRE mire = NULL;
341  int nmire = 0;
342  const char * s;
343  int xx;
344  int i;
345 
346  s = rpmExpand(str, NULL);
347  if (s && *s) {
348  xx = poptParseArgvString(s, &ac, (const char ***)&av);
349  s = _free(s);
350  }
351  if (ac == 0 || av == NULL || *av == NULL) {
352  s = _free(s);
353  goto exit;
354  }
355 
356  for (i = 0; i < ac; i++) {
357  xx = mireAppend(RPMMIRE_REGEX, 0, av[i], NULL, &mire, &nmire);
358  /* XXX add REG_NOSUB? better error msg? */
359  if (xx) {
361  _("Compilation of pattern '%s'"
362  " (expanded from '%s') failed. Skipping ...\n"),
363  av[i], str);
364  nmire--; /* XXX does this actually skip?!? */
365  }
366  }
367  if (nmire == 0)
368  mire = mireFree(mire);
369 
370 exit:
371  av = _free(av);
372  if (nmirep)
373  *nmirep = nmire;
374  return mire;
375 }
376 
377 static int rpmfcMatchRegexps(void * _mire, int nmire,
378  const char * str, char deptype)
379  /*@modifies mires @*/
380 {
381  miRE mire = (miRE) _mire;
382  int xx;
383  int i;
384 
385  for (i = 0; i < nmire; i++) {
386 #ifdef DYING /* XXX noisy. use --miredebug if you need this spewage */
387  rpmlog(RPMLOG_DEBUG, D_("Checking %c: '%s'\n"), deptype, str);
388 #endif
389  if ((xx = mireRegexec(mire + i, str, 0)) < 0)
390  continue;
391  rpmlog(RPMLOG_NOTICE, _("Skipping %c: '%s'\n"), deptype, str);
392  return 1;
393  }
394  return 0;
395 }
396 
397 /*@null@*/
398 static void * rpmfcFreeRegexps(/*@only@*/ void * _mire, int nmire)
399  /*@modifies mires @*/
400 {
401  miRE mire = (miRE) _mire;
402 /*@-refcounttrans@*/
403  return mireFreeAll(mire, nmire);
404 /*@=refcounttrans@*/
405 }
406 
414 static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char * nsdep)
415  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
416  /*@modifies fc, rpmGlobalMacroContext, fileSystem, internalState @*/
417 {
418  miRE mire = NULL;
419  int nmire = 0;
420  const char * fn = fc->fn[fc->ix];
421  char buf[BUFSIZ];
422  rpmiob iob_stdout = NULL;
423  rpmiob iob_stdin;
424  const char *av[2];
425  rpmds * depsp, ds;
426  const char * N;
427  const char * EVR;
428  rpmTag tagN;
429  evrFlags Flags;
430  evrFlags dsContext;
431  ARGV_t pav;
432  const char * s;
433  int pac;
434  int xx;
435  int i;
436 
437  switch (deptype) {
438  default:
439  return -1;
440  /*@notreached@*/ break;
441  case 'P':
442  if (fc->skipProv)
443  return 0;
444  xx = snprintf(buf, sizeof(buf), "%%{?__%s_provides}", nsdep);
445  depsp = &fc->provides;
446  dsContext = RPMSENSE_FIND_PROVIDES;
447  tagN = RPMTAG_PROVIDENAME;
448  mire = (miRE) fc->Pmires;
449  nmire = fc->Pnmire;
450  break;
451  case 'R':
452  if (fc->skipReq)
453  return 0;
454  xx = snprintf(buf, sizeof(buf), "%%{?__%s_requires}", nsdep);
455  depsp = &fc->requires;
456  dsContext = RPMSENSE_FIND_REQUIRES;
457  tagN = RPMTAG_REQUIRENAME;
458  mire = (miRE) fc->Rmires;
459  nmire = fc->Rnmire;
460  break;
461  }
462  buf[sizeof(buf)-1] = '\0';
463  av[0] = buf;
464  av[1] = NULL;
465 
466  iob_stdin = rpmiobNew(0);
467  iob_stdin = rpmiobAppend(iob_stdin, fn, 1);
468  iob_stdout = NULL;
469  xx = rpmfcExec(av, iob_stdin, &iob_stdout, 0);
470  iob_stdin = rpmiobFree(iob_stdin);
471 
472  if (xx == 0 && iob_stdout != NULL) {
473  pav = NULL;
474  xx = argvSplit(&pav, rpmiobStr(iob_stdout), " \t\n\r");
475  pac = argvCount(pav);
476  if (pav)
477  for (i = 0; i < pac; i++) {
478  N = pav[i];
479  EVR = "";
480  Flags = dsContext;
481  if (pav[i+1] && strchr("=<>", *pav[i+1])) {
482  i++;
483  for (s = pav[i]; *s; s++) {
484  switch(*s) {
485  default:
486 assert(*s != '\0');
487  /*@switchbreak@*/ break;
488  case '=':
489  Flags = (evrFlags) (Flags | RPMSENSE_EQUAL);
490  /*@switchbreak@*/ break;
491  case '<':
492  Flags = (evrFlags) (Flags | RPMSENSE_LESS);
493  /*@switchbreak@*/ break;
494  case '>':
495  Flags = (evrFlags) (Flags | RPMSENSE_GREATER);
496  /*@switchbreak@*/ break;
497  }
498  }
499  i++;
500  EVR = pav[i];
501  if(EVR == NULL) {
502  rpmlog(RPMLOG_ERR, _("%s helper returned empty version info for %s, omitting\n"), nsdep, N);
503  continue;
504  }
505  }
506 
507  if (_filter_values && rpmfcMatchRegexps(mire, nmire, N, deptype))
508  continue;
509 
510  /* Add tracking dependency for versioned Provides: */
511  if (!fc->tracked && deptype == 'P' && *EVR != '\0') {
512  static evrFlags _Flags = (evrFlags)
513  (RPMSENSE_RPMLIB|(RPMSENSE_LESS|RPMSENSE_EQUAL));
515  "rpmlib(VersionedDependencies)", "3.0.3-1",
516  _Flags);
517  xx = rpmdsMerge(&fc->requires, ds);
518  (void)rpmdsFree(ds);
519  ds = NULL;
520  fc->tracked = 1;
521  }
522 
523  ds = rpmdsSingle(tagN, N, EVR, Flags);
524 
525 #if defined(RPM_VENDOR_MANDRIVA) /* filter-overlapping-dependencies */
526  int overlap = 0;
527  if (*depsp) {
528  int ix = rpmdsSearch(*depsp, ds);
529  if (ix >= 0) {
530  EVR_t lEVR = rpmEVRnew(RPMSENSE_ANY, 0),
531  rEVR = rpmEVRnew(RPMSENSE_ANY, 0);
532 
533  rpmdsSetIx(*depsp, ix);
534 
535  rpmEVRparse(rpmdsEVR(*depsp), lEVR);
536  rpmEVRparse(EVR, rEVR);
537  lEVR->Flags = rpmdsFlags(*depsp) | RPMSENSE_EQUAL;
538  rEVR->Flags = Flags | RPMSENSE_EQUAL;
539 
540  if (rpmEVRcompare(lEVR, rEVR) < 0) {
541  (*depsp)->EVR[(*depsp)->i] = EVR;
542  (*depsp)->Flags[(*depsp)->i] = Flags;
543  overlap = 1;
544  }
545  lEVR = rpmEVRfree(lEVR);
546  rEVR = rpmEVRfree(rEVR);
547  }
548  }
549  if (!overlap)
550 #endif
551  /* Add to package dependencies. */
552  xx = rpmdsMerge(depsp, ds);
553 
554  /* Add to file dependencies. */
555  xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
556 
557  (void)rpmdsFree(ds);
558  ds = NULL;
559  }
560 
561  pav = argvFree(pav);
562  }
563  iob_stdout = rpmiobFree(iob_stdout);
564 
565  return 0;
566 }
567 
570 /*@-nullassign@*/
571 /*@unchecked@*/ /*@observer@*/
572 static struct rpmfcTokens_s rpmfcTokens[] = {
573  { "directory", RPMFC_DIRECTORY|RPMFC_INCLUDE },
574 
575  { " shared object", RPMFC_LIBRARY },
576  { " executable", RPMFC_EXECUTABLE },
577  { " statically linked", RPMFC_STATIC },
578  { " not stripped", RPMFC_NOTSTRIPPED },
579  { " archive", RPMFC_ARCHIVE },
580 
581  { "MIPS, N32 MIPS32", RPMFC_ELFMIPSN32|RPMFC_INCLUDE },
582  { "ELF 32-bit", RPMFC_ELF32|RPMFC_INCLUDE },
583  { "ELF 64-bit", RPMFC_ELF64|RPMFC_INCLUDE },
584 // { "ELF 32-bit", RPMFC_ELFX32|RPMFC_INCLUDE },
585 
586  { " script", RPMFC_SCRIPT },
587  { " text", RPMFC_TEXT },
588  { " document", RPMFC_DOCUMENT },
589 
590  { " compressed", RPMFC_COMPRESSED },
591 
592  { "troff or preprocessor input", RPMFC_MANPAGE|RPMFC_INCLUDE },
593  { "GNU Info", RPMFC_MANPAGE|RPMFC_INCLUDE },
594 
595  { "Desktop Entry", RPMFC_DESKTOP_FILE|RPMFC_INCLUDE },
596 
597  { "perl script text", RPMFC_PERL|RPMFC_INCLUDE },
598  { "Perl script", RPMFC_PERL|RPMFC_INCLUDE },
599  { "Perl5 module source text", RPMFC_PERL|RPMFC_MODULE|RPMFC_INCLUDE },
600 
601  { "PHP script text", RPMFC_PHP|RPMFC_INCLUDE },
602  { "G-IR binary database", RPMFC_TYPELIB|RPMFC_INCLUDE },
603 
604  /* XXX "a /usr/bin/python -t script text executable" */
605  /* XXX "python 2.3 byte-compiled" */
606  { " /usr/bin/python", RPMFC_PYTHON|RPMFC_INCLUDE },
607 
608  { "libtool library ", RPMFC_LIBTOOL|RPMFC_INCLUDE },
609  { "pkgconfig ", RPMFC_PKGCONFIG|RPMFC_INCLUDE },
610 
611  { "Bourne ", RPMFC_BOURNE|RPMFC_INCLUDE },
612  { "Bourne-Again ", RPMFC_BOURNE|RPMFC_INCLUDE },
613 
614  { "Java ", RPMFC_JAVA|RPMFC_INCLUDE },
615 
616  { "Mono/.Net assembly", RPMFC_MONO|RPMFC_INCLUDE },
617 
618  { "ruby script text", RPMFC_RUBY|RPMFC_INCLUDE },
619  { "Ruby script text", RPMFC_RUBY|RPMFC_INCLUDE },
620 
621  { "current ar archive", RPMFC_STATIC|RPMFC_LIBRARY|RPMFC_ARCHIVE|RPMFC_INCLUDE },
622 
623  { "Zip archive data", RPMFC_COMPRESSED|RPMFC_ARCHIVE|RPMFC_INCLUDE },
624  { "tar archive", RPMFC_ARCHIVE|RPMFC_INCLUDE },
625  { "cpio archive", RPMFC_ARCHIVE|RPMFC_INCLUDE },
626  { "RPM v3", RPMFC_ARCHIVE|RPMFC_INCLUDE },
627  { "RPM v4", RPMFC_ARCHIVE|RPMFC_INCLUDE },
628 
629  { " image", RPMFC_IMAGE|RPMFC_INCLUDE },
630  { " font", RPMFC_FONT|RPMFC_INCLUDE },
631  { " Font", RPMFC_FONT|RPMFC_INCLUDE },
632 
633  { " commands", RPMFC_SCRIPT|RPMFC_INCLUDE },
634  { " script", RPMFC_SCRIPT|RPMFC_INCLUDE },
635 
636  { "empty", RPMFC_WHITE|RPMFC_INCLUDE },
637 
638  { "HTML", RPMFC_WHITE|RPMFC_INCLUDE },
639  { "SGML", RPMFC_WHITE|RPMFC_INCLUDE },
640  { "XML", RPMFC_WHITE|RPMFC_INCLUDE },
641 
642  { " program text", RPMFC_WHITE|RPMFC_INCLUDE },
643  { " source", RPMFC_WHITE|RPMFC_INCLUDE },
644  { "GLS_BINARY_LSB_FIRST", RPMFC_WHITE|RPMFC_INCLUDE },
645  { " DB ", RPMFC_WHITE|RPMFC_INCLUDE },
646 
647  { "ASCII English text", RPMFC_WHITE|RPMFC_INCLUDE },
648  { "ASCII text", RPMFC_WHITE|RPMFC_INCLUDE },
649  { "ISO-8859 text", RPMFC_WHITE|RPMFC_INCLUDE },
650 
651  { "symbolic link to", RPMFC_SYMLINK },
652  { "socket", RPMFC_DEVICE },
653  { "special", RPMFC_DEVICE },
654 
655  { "ASCII", RPMFC_WHITE },
656  { "ISO-8859", RPMFC_WHITE },
657 
658  { "data", RPMFC_WHITE },
659 
660  { "application", RPMFC_WHITE },
661  { "boot", RPMFC_WHITE },
662  { "catalog", RPMFC_WHITE },
663  { "code", RPMFC_WHITE },
664  { "file", RPMFC_WHITE },
665  { "format", RPMFC_WHITE },
666  { "message", RPMFC_WHITE },
667  { "program", RPMFC_WHITE },
668 
669  { "broken symbolic link to ", RPMFC_WHITE|RPMFC_ERROR },
670  { "can't read", RPMFC_WHITE|RPMFC_ERROR },
671  { "can't stat", RPMFC_WHITE|RPMFC_ERROR },
672  { "executable, can't read", RPMFC_WHITE|RPMFC_ERROR },
673  { "core file", RPMFC_WHITE|RPMFC_ERROR },
674 
675  { NULL, RPMFC_BLACK }
676 };
677 /*@=nullassign@*/
678 
679 int rpmfcColoring(const char * fmstr)
680 {
681  rpmfcToken fct;
682  int fcolor = RPMFC_BLACK;
683 
684  for (fct = rpmfcTokens; fct->token != NULL; fct++) {
685  if (strstr(fmstr, fct->token) == NULL)
686  continue;
687  // This is a nasty hack, but will have to do for now
688  if ((fct->colors & RPMFC_ELF32) && (strstr(fmstr, "x86-64") != NULL))
689  fcolor |= RPMFC_ELFX32|RPMFC_INCLUDE;
690  else
691  fcolor |= fct->colors;
692  if (fcolor & RPMFC_INCLUDE)
693  return fcolor;
694  }
695  return fcolor;
696 }
697 
698 void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
699 {
700  int fcolor;
701  int ndx;
702  int cx;
703  int dx;
704  size_t fx;
705 
706 unsigned nprovides;
707 unsigned nrequires;
708 
709  if (fp == NULL) fp = stderr;
710 
711  if (msg)
712  fprintf(fp, "===================================== %s\n", msg);
713 
714 nprovides = rpmdsCount(fc->provides);
715 nrequires = rpmdsCount(fc->requires);
716 
717  if (fc)
718  for (fx = 0; fx < fc->nfiles; fx++) {
719 assert(fx < fc->fcdictx->nvals);
720  cx = fc->fcdictx->vals[fx];
721 assert(fx < fc->fcolor->nvals);
722  fcolor = fc->fcolor->vals[fx];
723 
724  fprintf(fp, "%3d %s", (int)fx, fc->fn[fx]);
725  if (fcolor != RPMFC_BLACK)
726  fprintf(fp, "\t0x%x", fc->fcolor->vals[fx]);
727  else
728  fprintf(fp, "\t%s", fc->cdict[cx]);
729  fprintf(fp, "\n");
730 
731  if (fc->fddictx == NULL || fc->fddictn == NULL)
732  continue;
733 
734 assert(fx < fc->fddictx->nvals);
735  dx = fc->fddictx->vals[fx];
736 assert(fx < fc->fddictn->nvals);
737  ndx = fc->fddictn->vals[fx];
738 
739  while (ndx-- > 0) {
740  const char * depval;
741  unsigned char deptype;
742  unsigned ix;
743 
744  ix = fc->ddictx->vals[dx++];
745  deptype = ((ix >> 24) & 0xff);
746  ix &= 0x00ffffff;
747  depval = NULL;
748  switch (deptype) {
749  default:
750 assert(depval != NULL);
751  /*@switchbreak@*/ break;
752  case 'P':
753  if (nprovides > 0) {
754 assert(ix < nprovides);
755  (void) rpmdsSetIx(fc->provides, ix-1);
756  if (rpmdsNext(fc->provides) >= 0)
757  depval = rpmdsDNEVR(fc->provides);
758  }
759  /*@switchbreak@*/ break;
760  case 'R':
761  if (nrequires > 0) {
762 assert(ix < nrequires);
763  (void) rpmdsSetIx(fc->requires, ix-1);
764  if (rpmdsNext(fc->requires) >= 0)
765  depval = rpmdsDNEVR(fc->requires);
766  }
767  /*@switchbreak@*/ break;
768  }
769  if (depval)
770  fprintf(fp, "\t%s\n", depval);
771  }
772  }
773 }
774 
780 static int rpmfcSCRIPT(rpmfc fc)
781  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
782  /*@modifies fc, rpmGlobalMacroContext, fileSystem, internalState @*/
783 {
784  const char * fn = fc->fn[fc->ix];
785  const char * bn;
786  rpmds ds;
787  char buf[BUFSIZ];
788  FILE * fp;
789  char * s, * se;
790  int i;
791  int is_executable;
792  int xx;
793 
794  /* Don't generate dependencies from files shipped as documentation */
795  if (!rpmExpandNumeric("%{_generate_dependencies_from_docdir}")) {
796  const char * defaultdocdir = rpmExpand("%{?_defaultdocdir}", NULL);
797  if (defaultdocdir == NULL || *defaultdocdir == '\0')
798  defaultdocdir = strdup("/usr/share/doc");
799  xx = !strncmp(fn+fc->brlen, defaultdocdir, strlen(defaultdocdir));
800  defaultdocdir = _free(defaultdocdir) ;
801  if (xx)
802  return 0;
803  }
804 
805  /* Extract dependencies only from files with executable bit set. */
806  { struct stat sb, * st = &sb;
807  if (stat(fn, st) != 0)
808  return -1;
809  is_executable = (int)(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
810  }
811 
812  fp = fopen(fn, "r");
813  if (fp == NULL || ferror(fp)) {
814  if (fp) (void) fclose(fp);
815  return -1;
816  }
817 
818  /* Look for #! interpreter in first 10 lines. */
819  for (i = 0; i < 10; i++) {
820 
821  s = fgets(buf, sizeof(buf) - 1, fp);
822  if (s == NULL || ferror(fp) || feof(fp))
823  break;
824  s[sizeof(buf)-1] = '\0';
825  if (!(s[0] == '#' && s[1] == '!'))
826  continue;
827  s += 2;
828 
829  while (*s && strchr(" \t\n\r", *s) != NULL)
830  s++;
831  if (*s == '\0')
832  continue;
833  if (*s != '/')
834  continue;
835 
836  for (se = s+1; *se; se++) {
837  if (strchr(" \t\n\r", *se) != NULL)
838  /*@innerbreak@*/ break;
839  }
840  *se = '\0';
841  se++;
842 
843  if (!_filter_values
844  || (!fc->skipReq
845  && !rpmfcMatchRegexps(fc->Rmires, fc->Rnmire, s, 'R')))
846  if (is_executable) {
847  /* Add to package requires. */
848  ds = rpmdsSingle(RPMTAG_REQUIRENAME, s, "", RPMSENSE_FIND_REQUIRES);
849  xx = rpmdsMerge(&fc->requires, ds);
850 
851  /* Add to file requires. */
852  xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(se, fc->ix, ds));
853 
854  (void)rpmdsFree(ds);
855  ds = NULL;
856  }
857 
858  /* Set color based on interpreter name. */
859  /* XXX magic token should have already done this?!? */
860 /*@-moduncon@*/
861  bn = basename(s);
862 /*@=moduncon@*/
863  if (!strcmp(bn, "perl"))
864  fc->fcolor->vals[fc->ix] |= RPMFC_PERL;
865  else if (!strncmp(bn, "python", sizeof("python")-1))
866  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
867  else if (!strncmp(bn, "php", sizeof("php")-1))
868  fc->fcolor->vals[fc->ix] |= RPMFC_PHP;
869  else if (!strncmp(bn, "ruby", sizeof("ruby")-1))
870  fc->fcolor->vals[fc->ix] |= RPMFC_RUBY;
871 
872  break;
873  }
874 
875  (void) fclose(fp);
876 
877  if (fc->fcolor->vals[fc->ix] & RPMFC_PERL) {
878  if (fc->fcolor->vals[fc->ix] & RPMFC_MODULE)
879  xx = rpmfcHelper(fc, 'P', "perl");
880  if (is_executable || (fc->fcolor->vals[fc->ix] & RPMFC_MODULE))
881  xx = rpmfcHelper(fc, 'R', "perl");
882  } else
883  if (fc->fcolor->vals[fc->ix] & RPMFC_PYTHON) {
884  xx = rpmfcHelper(fc, 'P', "python");
885 #ifdef NOTYET
886  if (is_executable)
887 #endif
888  xx = rpmfcHelper(fc, 'R', "python");
889  } else
890  if (fc->fcolor->vals[fc->ix] & RPMFC_LIBTOOL) {
891  xx = rpmfcHelper(fc, 'P', "libtool");
892 #ifdef NOTYET
893  if (is_executable)
894 #endif
895  xx = rpmfcHelper(fc, 'R', "libtool");
896  } else
897  if (fc->fcolor->vals[fc->ix] & RPMFC_PKGCONFIG) {
898  xx = rpmfcHelper(fc, 'P', "pkgconfig");
899 #ifdef NOTYET
900  if (is_executable)
901 #endif
902  xx = rpmfcHelper(fc, 'R', "pkgconfig");
903  } else
904  if (fc->fcolor->vals[fc->ix] & RPMFC_BOURNE) {
905 #ifdef NOTYET
906  xx = rpmfcHelper(fc, 'P', "executable");
907 #endif
908  if (is_executable)
909  xx = rpmfcHelper(fc, 'R', "executable");
910  } else
911  if (fc->fcolor->vals[fc->ix] & RPMFC_PHP) {
912  xx = rpmfcHelper(fc, 'P', "php");
913  /* not only executable, files run by httpd usually are not */
914  xx = rpmfcHelper(fc, 'R', "php");
915  } else
916  if (fc->fcolor->vals[fc->ix] & RPMFC_MONO) {
917  xx = rpmfcHelper(fc, 'P', "mono");
918  if (is_executable)
919  xx = rpmfcHelper(fc, 'R', "mono");
920  } else
921  if (fc->fcolor->vals[fc->ix] & RPMFC_RUBY) {
922  xx = rpmfcHelper(fc, 'P', "ruby");
923 #ifdef NOTYET
924  if (is_executable)
925 #endif
926  xx = rpmfcHelper(fc, 'R', "ruby");
927  } else
928  if ((fc->fcolor->vals[fc->ix] & RPMFC_FONT) == RPMFC_FONT) {
929  xx = rpmfcHelper(fc, 'P', "font");
930  /* XXX: currently of no use, but for the sake of consistency... */
931  xx = rpmfcHelper(fc, 'R', "font");
932  } else
933  if (fc->fcolor->vals[fc->ix] & RPMFC_HASKELL) {
934  xx = rpmfcHelper(fc, 'P', "haskell");
935  xx = rpmfcHelper(fc, 'R', "haskell");
936  } else
937  if (fc->fcolor->vals[fc->ix] & RPMFC_TYPELIB) {
938  xx = rpmfcHelper(fc, 'P', "typelib");
939 #ifdef NOTYET
940  if (is_executable)
941 #endif
942  xx = rpmfcHelper(fc, 'R', "typelib");
943  } else
944  if ((fc->fcolor->vals[fc->ix] & (RPMFC_MODULE|RPMFC_LIBRARY)) &&
945  strstr(fn, "/gstreamer")) {
946  xx = rpmfcHelper(fc, 'P', "gstreamer");
947  /* XXX: currently of no use, but for the sake of consistency... */
948  xx = rpmfcHelper(fc, 'R', "gstreamer");
949 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_PLD)
950  } else
951  if ((fc->fcolor->vals[fc->ix] & RPMFC_MODULE)) {
953  if (!mireRegcomp(mire, "^.*((/lib/modules/|/var/lib/dkms/).*\\.ko(\\.gz|\\.xz)?|(/var/lib/dkms-binary/[^/]+/[^/]+|/usr/src)/[^/]+/dkms.conf)$"))
954  if (mireRegexec(mire, fc->fn[fc->ix], (size_t) 0) >= 0) {
955  fc->fcolor->vals[fc->ix] |= (RPMFC_MODULE|RPMFC_SCRIPT);
956  xx = rpmfcHelper(fc, 'P', "kernel");
957  /* XXX: currently of no use, but for the sake of consistency... */
958  xx = rpmfcHelper(fc, 'R', "kernel");
959  }
960  mire = mireFree(mire);
961 #endif
962  } else
963  if (fc->fcolor->vals[fc->ix] & RPMFC_JAVA) {
964  xx = rpmfcHelper(fc, 'P', "java");
965  xx = rpmfcHelper(fc, 'R', "java");
966  } else
967  if (fc->fcolor->vals[fc->ix] & RPMFC_DESKTOP_FILE) {
968  xx = rpmfcHelper(fc, 'P', "mimetype");
969  }
970 
971 /*@=observertrans@*/
972  return 0;
973 }
974 
981 static int rpmfcMergePR(void * context, rpmds ds)
982  /*@globals fileSystem, internalState @*/
983  /*@modifies ds, fileSystem, internalState @*/
984 {
985  rpmfc fc = (rpmfc) context;
986  char buf[BUFSIZ];
987  int rc = 0;
988 
989 if (_rpmfc_debug < 0)
990 fprintf(stderr, "*** rpmfcMergePR(%p, %p) %s\n", context, ds, tagName(rpmdsTagN(ds)));
991  switch(rpmdsTagN(ds)) {
992  default:
993  rc = -1;
994  break;
995  case RPMTAG_PROVIDENAME:
996  if (!_filter_values
997  || (!fc->skipProv
998  && !rpmfcMatchRegexps(fc->Pmires, fc->Pnmire, ds->N[0], 'P')))
999  {
1000  /* Add to package provides. */
1001  rc = rpmdsMerge(&fc->provides, ds);
1002 
1003  /* Add to file dependencies. */
1004  buf[0] = '\0';
1005  rc = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
1006  }
1007  break;
1008  case RPMTAG_REQUIRENAME:
1009  if (!_filter_values
1010  || (!fc->skipReq
1011  && !rpmfcMatchRegexps(fc->Rmires, fc->Rnmire, ds->N[0], 'R')))
1012  {
1013  /* Add to package requires. */
1014  rc = rpmdsMerge(&fc->requires, ds);
1015 
1016  /* Add to file dependencies. */
1017  buf[0] = '\0';
1018  rc = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
1019  }
1020  break;
1021  }
1022  return rc;
1023 }
1024 
1030 static int rpmfcELF(rpmfc fc)
1031  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1032  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
1033 {
1034  const char * fn = fc->fn[fc->ix];
1035  int flags = 0;
1036 
1037  if (fc->skipProv)
1038  flags |= RPMELF_FLAG_SKIPPROVIDES;
1039  if (fc->skipReq)
1040  flags |= RPMELF_FLAG_SKIPREQUIRES;
1041 
1042  return rpmdsELF(fn, flags, rpmfcMergePR, fc);
1043 }
1044 
1045 #if defined(RPM_VENDOR_MANDRIVA)
1046 
1055 extern int rpmdsSymlink(const char * fn, int flags,
1056  int (*add) (void * context, rpmds ds), void * context)
1057  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1058  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/;
1059 
1060 static int rpmfcSYMLINK(rpmfc fc)
1061  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1062  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
1063 {
1064  const char * fn = fc->fn[fc->ix];
1065  int flags = 0;
1066 
1067  if (fc->skipProv)
1068  flags |= RPMELF_FLAG_SKIPPROVIDES;
1069  if (fc->skipReq)
1070  flags |= RPMELF_FLAG_SKIPREQUIRES;
1071 
1072  return rpmdsSymlink(fn, flags, rpmfcMergePR, fc);
1073 }
1074 #endif /* RPM_VENDOR_MANDRIVA */
1075 
1076 typedef struct rpmfcApplyTbl_s {
1077  int (*func) (rpmfc fc);
1079 } * rpmfcApplyTbl;
1080 
1084 /*@-nullassign@*/
1085 /*@unchecked@*/
1087  { rpmfcELF, RPMFC_ELF },
1089 #if defined(RPM_VENDOR_MANDRIVA)
1090  { rpmfcSYMLINK, RPMFC_SYMLINK },
1091 #endif
1092  { NULL, 0 }
1093 };
1094 /*@=nullassign@*/
1095 
1097 {
1098  rpmfcApplyTbl fcat;
1099  const char * s;
1100  char * se;
1101  rpmds ds;
1102  const char * fn;
1103  const char * N;
1104  const char * EVR;
1105  evrFlags Flags;
1106  unsigned char deptype;
1107  int nddict;
1108  int previx;
1109  unsigned int val;
1110  int dix;
1111  int ix;
1112  int i;
1113  int xx;
1114  int skipping;
1115  int l;
1116  const char * lastPycDir = NULL;
1117  const char * p;
1118 
1119  miRE mire;
1120  int skipProv = fc->skipProv;
1121  int skipReq = fc->skipReq;
1122  int j;
1123 
1124  if (_filter_execs) {
1125  fc->PFnmire = 0;
1126  fc->PFmires = rpmfcExpandRegexps("%{?__noautoprovfiles}", &fc->PFnmire);
1127  if (fc->PFnmire > 0)
1128  rpmlog(RPMLOG_DEBUG, D_("added %d %%__noautoprovfiles patterns.\n"),
1129  fc->PFnmire);
1130  fc->RFnmire = 0;
1131  fc->RFmires = rpmfcExpandRegexps("%{?__noautoreqfiles}", &fc->RFnmire);
1132  if (fc->RFnmire > 0)
1133  rpmlog(RPMLOG_DEBUG, D_("added %d %%__noautoreqfiles patterns.\n"),
1134  fc->RFnmire);
1135  fc->Pnmire = 0;
1136  fc->Pmires = rpmfcExpandRegexps("%{?__noautoprov}", &fc->Pnmire);
1137  if (fc->Pnmire > 0)
1138  rpmlog(RPMLOG_DEBUG, D_("added %d %%__noautoprov patterns.\n"),
1139  fc->Pnmire);
1140  fc->Rnmire = 0;
1141  fc->Rmires = rpmfcExpandRegexps("%{?__noautoreq}", &fc->Rnmire);
1142  if (fc->Rnmire > 0)
1143  rpmlog(RPMLOG_DEBUG, D_("added %d %%__noautoreq patterns.\n"),
1144  fc->Rnmire);
1145  }
1146 
1147 /* Make sure something didn't go wrong previously! */
1148 assert(fc->fn != NULL);
1149  /* Generate package and per-file dependencies. */
1150  for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) {
1151 
1152  /* XXX Insure that /usr/{share,lib{,64}}/python files are marked RPMFC_PYTHON */
1153  /* XXX HACK: classification by path is intrinsically stupid. */
1154  { fn = strstr(fc->fn[fc->ix], "/usr/lib");
1155  if (fn) {
1156  fn += sizeof("/usr/lib")-1;
1157  if (fn[0] == 'x') fn++;
1158  if ((fn[0] == '3' && fn[1] == '2') ||
1159  (fn[0] == '6' && fn[1] == '4'))
1160  fn += 2;
1161  if (!strncmp(fn, "/python", sizeof("/python")-1)) {
1162  l = strlen(fn);
1163  if (fn[l-4] == '.' && fn[l-3] == 'p' && fn[l-2] == 'y'
1164  && (fn[l-1] == 'c' || fn[l-1] == 'o')) {
1165  p = strchr(fn, '/');
1166  if (p) {
1167  l = p - fc->fn[fc->ix];
1168  if (!lastPycDir || strncmp(lastPycDir, fc->fn[fc->ix], l)) {
1169  /* one pyc/pyo file per python library directory should be enough to get the dependency */
1170  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
1171  lastPycDir = fc->fn[fc->ix];
1172  }
1173  }
1174  }
1175  else if (l > 17 && !strcmp(fn + l - 17, "egg-info/PKG-INFO")) {
1176  /* get all PKG-INFO files for egg-info data */
1177  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
1178  }
1179  else if (l > 8 && !strcmp(fn + l - 8, "egg-info")) {
1180  /* get all .egg-info files too */
1181  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
1182  }
1183  }
1184  else if (!strncmp(fn, "/ruby", sizeof("/ruby")-1)) {
1185  fc->fcolor->vals[fc->ix] |= RPMFC_RUBY;
1186  if ((strstr(fn, ".gemspec") || strstr(fn, "rbconfig.rb"))) {
1188  if (!mireRegcomp(mire, ".*/(specifications/.*\\.gemspec|rbconfig\\.rb)$"))
1189  if (mireRegexec(mire, fc->fn[fc->ix], (size_t) 0) >= 0)
1190  fc->fcolor->vals[fc->ix] |= RPMFC_MODULE;
1191  mire = mireFree(mire);
1192  }
1193  }
1194  /* XXX: lacking better, more generic classifier... */
1195  else if (!strncmp(fn, "/gstreamer", sizeof("/gstreamer")-1) &&
1196  fc->fcolor->vals[fc->ix] & RPMFC_LIBRARY)
1197  fc->fcolor->vals[fc->ix] |= (RPMFC_MODULE|RPMFC_SCRIPT);
1198 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_PLD)
1199  } else {
1201  if (!mireRegcomp(mire, "^.*((/lib/modules/|/var/lib/dkms/).*\\.ko(\\.gz|\\.xz)?|(/var/lib/dkms-binary/[^/]+/[^/]+|/usr/src)/[^/]+/dkms.conf)$"))
1202  if (mireRegexec(mire, fc->fn[fc->ix], (size_t) 0) >= 0)
1203  fc->fcolor->vals[fc->ix] |= (RPMFC_MODULE|RPMFC_SCRIPT);
1204  mire = mireFree(mire);
1205 #endif
1206  }
1207  fn = strstr(fc->fn[fc->ix], "/usr/share");
1208  if (fn) {
1209  fn += sizeof("/usr/share")-1;
1210  if (!strncmp(fn, "/python", sizeof("/python")-1)) {
1211  l = strlen(fn);
1212  if (fn[l-4] == '.' && fn[l-3] == 'p' && fn[l-2] == 'y'
1213  && (fn[l-1] == 'c' || fn[l-1] == 'o')) {
1214  p = strchr(fn, '/');
1215  if (p) {
1216  l = p - fc->fn[fc->ix];
1217  if (!lastPycDir || strncmp(lastPycDir, fc->fn[fc->ix], l)) {
1218  /* one pyc/pyo file per python library directory should be enough to get the dependency */
1219  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
1220  lastPycDir = fc->fn[fc->ix];
1221  }
1222  }
1223  }
1224  else if (l > 17 && !strcmp(fn + l - 17, "egg-info/PKG-INFO")) {
1225  /* get all PKG-INFO files for egg-info data */
1226  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
1227  }
1228  else if (l > 8 && !strcmp(fn + l - 8, "egg-info")) {
1229  /* get all .egg-info files too */
1230  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
1231  }
1232  }
1233  else if (!strncmp(fn, "/ruby", sizeof("/ruby")-1) || !strncmp(fn, "/gems/specifications", sizeof("/gems/specifications")-1)) {
1234  fc->fcolor->vals[fc->ix] |= RPMFC_RUBY;
1235  if ((strstr(fn, ".gemspec") || strstr(fn, "rbconfig.rb"))) {
1237  if (!mireRegcomp(mire, ".*/(specifications/.*\\.gemspec|rbconfig\\.rb)$"))
1238  if (mireRegexec(mire, fc->fn[fc->ix], (size_t) 0) >= 0)
1239  fc->fcolor->vals[fc->ix] |= RPMFC_MODULE;
1240  mire = mireFree(mire);
1241  }
1242  }
1243  }
1244  }
1245 
1246  /* XXX ugly quick & dirty integration of haskell() dependencies */
1247  { fn = strstr(fc->fn[fc->ix], "/usr/share/haskell-deps");
1248  if (fn)
1249  fc->fcolor->vals[fc->ix] |= RPMFC_HASKELL;
1250  }
1251 
1252  if (fc->fcolor->vals[fc->ix])
1253  for (fcat = rpmfcApplyTable; fcat->func != NULL; fcat++) {
1254  if (!(fc->fcolor->vals[fc->ix] & fcat->colormask))
1255  /*@innercontinue@*/ continue;
1256 
1257  if (_filter_execs) {
1258  fc->skipProv = skipProv;
1259  fc->skipReq = skipReq;
1260  if ((mire = (miRE)fc->PFmires) != NULL)
1261  for (j = 0; j < fc->PFnmire; j++, mire++) {
1262  fn = fc->fn[fc->ix] + fc->brlen;
1263  if ((xx = mireRegexec(mire, fn, 0)) < 0)
1264  /*@innercontinue@*/ continue;
1265  rpmlog(RPMLOG_NOTICE, _("skipping %s provides detection\n"),
1266  fn);
1267  fc->skipProv = 1;
1268  /*@innerbreak@*/ break;
1269  }
1270  if ((mire = (miRE)fc->RFmires) != NULL)
1271  for (j = 0; j < fc->RFnmire; j++, mire++) {
1272  fn = fc->fn[fc->ix] + fc->brlen;
1273  if ((xx = mireRegexec(mire, fn, 0)) < 0)
1274  /*@innercontinue@*/ continue;
1275  rpmlog(RPMLOG_NOTICE, _("skipping %s requires detection\n"),
1276  fn);
1277  fc->skipReq = 1;
1278  /*@innerbreak@*/ break;
1279  }
1280  }
1281 
1282  struct stat sb, * st = &sb;
1283  if (stat(fc->fn[fc->ix], st) == 0 && !(st->st_mode & (S_IFBLK|S_IFCHR)))
1284  xx = (*fcat->func) (fc);
1285  }
1286  }
1287 
1288  if (_filter_execs) {
1289  fc->PFmires = rpmfcFreeRegexps(fc->PFmires, fc->PFnmire);
1290  fc->RFmires = rpmfcFreeRegexps(fc->RFmires, fc->RFnmire);
1291  fc->Pmires = rpmfcFreeRegexps(fc->Pmires, fc->Pnmire);
1292  fc->Rmires = rpmfcFreeRegexps(fc->Rmires, fc->Rnmire);
1293  }
1294  fc->skipProv = skipProv;
1295  fc->skipReq = skipReq;
1296 
1297  /* Generate per-file indices into package dependencies. */
1298  nddict = argvCount(fc->ddict);
1299  previx = -1;
1300  for (i = 0; i < nddict; i++) {
1301  s = fc->ddict[i];
1302 
1303  /* Parse out (file#,deptype,N,EVR,Flags) */
1304  ix = strtol(s, &se, 10);
1305 assert(se != NULL);
1306  deptype = *se++;
1307  se++;
1308  N = se;
1309  while (*se && *se != ' ')
1310  se++;
1311  *se++ = '\0';
1312  EVR = se;
1313  while (*se && *se != ' ')
1314  se++;
1315  *se++ = '\0';
1316  Flags = (evrFlags) strtol(se, NULL, 16);
1317 
1318  dix = -1;
1319  skipping = 0;
1320  switch (deptype) {
1321  default:
1322  /*@switchbreak@*/ break;
1323  case 'P':
1324  skipping = fc->skipProv;
1325  ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
1326  dix = rpmdsFind(fc->provides, ds);
1327  (void)rpmdsFree(ds);
1328  ds = NULL;
1329  /*@switchbreak@*/ break;
1330  case 'R':
1331  skipping = fc->skipReq;
1332  ds = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags);
1333  dix = rpmdsFind(fc->requires, ds);
1334  (void)rpmdsFree(ds);
1335  ds = NULL;
1336  /*@switchbreak@*/ break;
1337  }
1338 
1339 /* XXX assertion incorrect while generating -debuginfo deps. */
1340 #if 0
1341 assert(dix >= 0);
1342 #else
1343  if (dix < 0)
1344  continue;
1345 #endif
1346 
1347  val = (deptype << 24) | (dix & 0x00ffffff);
1348  xx = argiAdd(&fc->ddictx, -1, val);
1349 
1350  if (previx != ix) {
1351  previx = ix;
1352  xx = argiAdd(&fc->fddictx, ix, argiCount(fc->ddictx)-1);
1353  }
1354  if (fc->fddictn && fc->fddictn->vals && !skipping)
1355  fc->fddictn->vals[ix]++;
1356  }
1357 
1358  return RPMRC_OK;
1359 }
1360 
1362 {
1363  ARGV_t fcav = NULL;
1364  ARGV_t dav;
1365  rpmmg mg = NULL;
1366  const char * s, * se;
1367  size_t slen;
1368  int fcolor;
1369  int xx;
1370  const char * magicfile = NULL;
1371 
1372  if (fc == NULL || argv == NULL)
1373  return RPMRC_OK;
1374 
1375  magicfile = rpmExpand("%{?_rpmfc_magic_path}", NULL);
1376  if (magicfile == NULL || *magicfile == '\0')
1377  magicfile = _free(magicfile);
1378 
1379  mg = rpmmgNew(magicfile, 0);
1380 assert(mg != NULL); /* XXX figger a proper return path. */
1381 
1382  fc->nfiles = argvCount(argv);
1383 
1384  /* Initialize the per-file dictionary indices. */
1385  xx = argiAdd(&fc->fddictx, fc->nfiles-1, 0);
1386  xx = argiAdd(&fc->fddictn, fc->nfiles-1, 0);
1387 
1388  /* Build (sorted) file class dictionary. */
1389  xx = argvAdd(&fc->cdict, "");
1390  xx = argvAdd(&fc->cdict, "directory");
1391 
1392  for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
1393  const char * ftype;
1394  int freeftype;
1395  rpmuint16_t mode = (fmode ? fmode[fc->ix] : 0);
1396  int urltype;
1397 
1398  ftype = ""; freeftype = 0;
1399  urltype = urlPath(argv[fc->ix], &s);
1400 assert(s != NULL && *s == '/');
1401  slen = strlen(s);
1402 
1403  switch (mode & S_IFMT) {
1404  case S_IFCHR: ftype = "character special"; /*@switchbreak@*/ break;
1405  case S_IFBLK: ftype = "block special"; /*@switchbreak@*/ break;
1406 #if defined(S_IFIFO)
1407  case S_IFIFO: ftype = "fifo (named pipe)"; /*@switchbreak@*/ break;
1408 #endif
1409 #if defined(S_IFSOCK)
1410 /*@-unrecog@*/
1411  case S_IFSOCK: ftype = "socket"; /*@switchbreak@*/ break;
1412 /*@=unrecog@*/
1413 #endif
1414  case S_IFDIR:
1415  case S_IFLNK:
1416  case S_IFREG:
1417  default:
1418 
1419 #define _suffix(_s, _x) \
1420  (slen >= sizeof(_x) && !strcmp((_s)+slen-(sizeof(_x)-1), (_x)))
1421 
1422  /* XXX all files with extension ".pm" are perl modules for now. */
1423  if (_suffix(s, ".pm"))
1424  ftype = "Perl5 module source text";
1425 
1426  /* XXX all files with extension ".jar" are java archives for now. */
1427  else if (_suffix(s, ".jar"))
1428  ftype = "Java archive file";
1429 
1430  /* XXX all files with extension ".class" are java class files for now. */
1431  else if (_suffix(s, ".class"))
1432  ftype = "Java class file";
1433 
1434  /* XXX all files with extension ".la" are libtool for now. */
1435  else if (_suffix(s, ".la"))
1436  ftype = "libtool library file";
1437 
1438  /* XXX all files with extension ".pc" are pkgconfig for now. */
1439  else if (_suffix(s, ".pc"))
1440  ftype = "pkgconfig file";
1441 
1442  /* XXX all files with extension ".php" are PHP for now. */
1443  else if (_suffix(s, ".php"))
1444  ftype = "PHP script text";
1445 
1446  else if (_suffix(s, ".desktop"))
1447  ftype = "Desktop Entry";
1448 
1449  /* XXX files with extension ".typelib" are GNOME typelib for now. */
1450  else if (_suffix(s, ".typelib"))
1451  ftype = "G-IR binary database";
1452 
1453  /* XXX files with extension ".js" have GNOME typelib requires for now */
1454  else if (_suffix(s, ".js"))
1455  ftype = "G-IR binary database";
1456 
1457  /* XXX skip all files in /dev/ which are (or should be) %dev dummies. */
1458  else if (slen >= fc->brlen+sizeof("/dev/") && !strncmp(s+fc->brlen, "/dev/", sizeof("/dev/")-1))
1459  ftype = "";
1460  else if (magicfile) {
1461  ftype = rpmmgFile(mg, s);
1462 assert(ftype != NULL); /* XXX never happens, rpmmgFile() returns "" */
1463  freeftype = 1;
1464  }
1465  /*@switchbreak@*/ break;
1466  }
1467 
1468  se = ftype;
1469 
1470 if (_rpmfc_debug) /* XXX noisy */
1471  rpmlog(RPMLOG_DEBUG, "%s: %s\n", s, se);
1472 
1473  /* Save the path. */
1474  xx = argvAdd(&fc->fn, s);
1475 
1476  /* Save the file type string. */
1477  xx = argvAdd(&fcav, se);
1478 
1479  /* Add (filtered) entry to sorted class dictionary. */
1480  fcolor = rpmfcColoring(se);
1481  xx = argiAdd(&fc->fcolor, (int)fc->ix, fcolor);
1482 
1483  if (fcolor != RPMFC_WHITE && (fcolor & RPMFC_INCLUDE))
1484  xx = rpmfcSaveArg(&fc->cdict, se);
1485 
1486 /*@-modobserver -observertrans @*/ /* XXX mixed types in variable */
1487  if (freeftype)
1488  ftype = _free(ftype);
1489 /*@=modobserver =observertrans @*/
1490  }
1491 
1492  /* Build per-file class index array. */
1493  fc->fknown = 0;
1494  for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
1495  se = fcav[fc->ix];
1496 assert(se != NULL);
1497 
1498  dav = argvSearch(fc->cdict, se, NULL);
1499  if (dav) {
1500  xx = argiAdd(&fc->fcdictx, (int)fc->ix, (dav - fc->cdict));
1501  fc->fknown++;
1502  } else {
1503  xx = argiAdd(&fc->fcdictx, (int)fc->ix, 0);
1504  fc->fwhite++;
1505  }
1506  }
1507 
1508  fcav = argvFree(fcav);
1509 
1510  mg = rpmmgFree(mg);
1512  D_("categorized %d files into %u classes (using %s).\n"),
1513  (unsigned)fc->nfiles, argvCount(fc->cdict), magicfile);
1514  magicfile = _free(magicfile);
1515 
1516  return RPMRC_OK;
1517 }
1518 
1521 typedef struct DepMsg_s * DepMsg_t;
1522 
1525 struct DepMsg_s {
1526 /*@observer@*/ /*@null@*/
1527  const char * msg;
1528 /*@observer@*/
1529  const char * argv[4];
1533  int mask;
1534  int toggle;
1535 };
1536 
1539 /*@-nullassign@*/
1540 /*@unchecked@*/
1541 static struct DepMsg_s depMsgs[] = {
1542  { "Provides", { "%{?__find_provides}", NULL, NULL, NULL },
1544  0, -1 },
1545  { "Requires(interp)", { NULL, "interp", NULL, NULL },
1547  _notpre(RPMSENSE_INTERP), 0 },
1548  { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL },
1549  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1550  _notpre(RPMSENSE_RPMLIB), 0 },
1551  { "Requires(verify)", { NULL, "verify", NULL, NULL },
1552  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1553  RPMSENSE_SCRIPT_VERIFY, 0 },
1554  { "Requires(pre)", { NULL, "pre", NULL, NULL },
1555  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1556  _notpre(RPMSENSE_SCRIPT_PRE), 0 },
1557  { "Requires(post)", { NULL, "post", NULL, NULL },
1558  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1559  _notpre(RPMSENSE_SCRIPT_POST), 0 },
1560  { "Requires(preun)", { NULL, "preun", NULL, NULL },
1561  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1562  _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
1563  { "Requires(postun)", { NULL, "postun", NULL, NULL },
1564  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1565  _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
1566  { "Requires", { "%{?__find_requires}", NULL, NULL, NULL },
1567  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS, /* XXX inherit name/version arrays */
1568  RPMSENSE_FIND_REQUIRES|RPMSENSE_TRIGGERIN|RPMSENSE_TRIGGERUN|RPMSENSE_TRIGGERPOSTUN|RPMSENSE_TRIGGERPREIN, 0 },
1569  { "Conflicts", { "%{?__find_conflicts}", NULL, NULL, NULL },
1571  0, -1 },
1572  { "Obsoletes", { "%{?__find_obsoletes}", NULL, NULL, NULL },
1574  0, -1 },
1575  { NULL, { NULL, NULL, NULL, NULL }, (rpmTag)0, (rpmTag)0, (rpmTag)0, 0, 0 }
1576 };
1577 /*@=nullassign@*/
1578 
1579 /*@unchecked@*/
1580 static DepMsg_t DepMsgs = depMsgs;
1581 
1586 static void printDeps(Header h)
1587  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1588  /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
1589 {
1590  DepMsg_t dm;
1591  rpmds ds = NULL;
1592  int flags = 0x2; /* XXX no filtering, !scareMem */
1593  const char * DNEVR;
1594  evrFlags Flags;
1595  int bingo = 0;
1596 
1597  for (dm = DepMsgs; dm->msg != NULL; dm++) {
1598  if ((int)dm->ntag != -1) {
1599  (void)rpmdsFree(ds);
1600  ds = NULL;
1601  ds = rpmdsNew(h, dm->ntag, flags);
1602  }
1603  if (dm->ftag == 0)
1604  continue;
1605 
1606  ds = rpmdsInit(ds);
1607  if (ds == NULL)
1608  continue; /* XXX can't happen */
1609 
1610  bingo = 0;
1611  while (rpmdsNext(ds) >= 0) {
1612 
1613  Flags = rpmdsFlags(ds);
1614 
1615  if (!((Flags & dm->mask) ^ (dm->toggle)))
1616  /*@innercontinue@*/ continue;
1617  if (bingo == 0) {
1618  rpmlog(RPMLOG_NOTICE, "%s:", (dm->msg ? dm->msg : ""));
1619  bingo = 1;
1620  }
1621  if ((DNEVR = rpmdsDNEVR(ds)) == NULL)
1622  /*@innercontinue@*/ continue; /* XXX can't happen */
1623  rpmlog(RPMLOG_NOTICE, " %s", DNEVR+2);
1624  }
1625  if (bingo)
1626  rpmlog(RPMLOG_NOTICE, "\n");
1627  }
1628  (void)rpmdsFree(ds);
1629  ds = NULL;
1630 }
1631 
1635  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1636  /*@modifies fi, rpmGlobalMacroContext, fileSystem, internalState @*/
1637 {
1638  rpmiob iob_stdin;
1639  rpmiob iob_stdout;
1640  DepMsg_t dm;
1641  int failnonzero = 0;
1642  rpmRC rc = RPMRC_OK;
1643 
1644  /*
1645  * Create file manifest buffer to deliver to dependency finder.
1646  */
1647  iob_stdin = rpmiobNew(0);
1648  fi = rpmfiInit(fi, 0);
1649  if (fi != NULL)
1650  while (rpmfiNext(fi) >= 0)
1651  iob_stdin = rpmiobAppend(iob_stdin, rpmfiFN(fi), 1);
1652 
1653  for (dm = DepMsgs; dm->msg != NULL; dm++) {
1654  rpmTag tag;
1655  rpmsenseFlags tagflags;
1656  char * s;
1657  int xx;
1658 
1659  tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
1660  tagflags = (rpmsenseFlags) 0;
1661  s = NULL;
1662 
1663  switch(tag) {
1664  case RPMTAG_PROVIDEFLAGS:
1665  if (!pkg->autoProv)
1666  continue;
1667  failnonzero = 1;
1668  tagflags = RPMSENSE_FIND_PROVIDES;
1669  /*@switchbreak@*/ break;
1670  case RPMTAG_REQUIREFLAGS:
1671  if (!pkg->autoReq)
1672  continue;
1673  failnonzero = 0;
1674  tagflags = RPMSENSE_FIND_REQUIRES;
1675  /*@switchbreak@*/ break;
1676  default:
1677  continue;
1678  /*@notreached@*/ /*@switchbreak@*/ break;
1679  }
1680 
1681  xx = rpmfcExec(dm->argv, iob_stdin, &iob_stdout, failnonzero);
1682  if (xx == -1)
1683  continue;
1684 
1685  s = rpmExpand(dm->argv[0], NULL);
1686  rpmlog(RPMLOG_NOTICE, _("Finding %s: %s\n"), dm->msg,
1687  (s ? s : ""));
1688  s = _free(s);
1689 
1690  if (iob_stdout == NULL) {
1691  rpmlog(RPMLOG_ERR, _("Failed to find %s:\n"), dm->msg);
1692  rc = RPMRC_FAIL;
1693  break;
1694  }
1695 
1696  /* Parse dependencies into header */
1697  if (spec->_parseRCPOT)
1698  rc = spec->_parseRCPOT(spec, pkg, rpmiobStr(iob_stdout), tag,
1699  0, tagflags);
1700  iob_stdout = rpmiobFree(iob_stdout);
1701 
1702  if (rc) {
1703  rpmlog(RPMLOG_ERR, _("Failed to find %s:\n"), dm->msg);
1704  break;
1705  }
1706  }
1707 
1708  iob_stdin = rpmiobFree(iob_stdin);
1709 
1710  return rc;
1711 }
1712 
1715 /*@-nullassign@*/
1716 /*@unchecked@*/
1717 static struct DepMsg_s scriptMsgs[] = {
1718  { "Requires(pre)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
1720  RPMSENSE_SCRIPT_PRE, 0 },
1721  { "Requires(post)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
1723  RPMSENSE_SCRIPT_POST, 0 },
1724  { "Requires(preun)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
1726  RPMSENSE_SCRIPT_PREUN, 0 },
1727  { "Requires(postun)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
1729  RPMSENSE_SCRIPT_POSTUN, 0 },
1730  { NULL, { NULL, NULL, NULL, NULL }, (rpmTag)0, (rpmTag)0, (rpmTag)0, 0, 0 }
1731 };
1732 /*@=nullassign@*/
1733 
1734 /*@unchecked@*/
1735 static DepMsg_t ScriptMsgs = scriptMsgs;
1736 
1739 static int rpmfcGenerateScriptletDeps(const Spec spec, Package pkg)
1740  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1741  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
1742 {
1743  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1744  rpmiob iob_stdin = rpmiobNew(0);
1745  rpmiob iob_stdout = NULL;
1746  DepMsg_t dm;
1747  int failnonzero = 0;
1748  int rc = 0;
1749  int xx;
1750 
1751  for (dm = ScriptMsgs; dm->msg != NULL; dm++) {
1752  rpmTag tag;
1753  rpmsenseFlags tagflags;
1754  char * s;
1755 
1756  tag = dm->ftag;
1757  tagflags = (rpmsenseFlags) (RPMSENSE_FIND_REQUIRES | dm->mask);
1758 
1759  /* Retrieve scriptlet interpreter. */
1760  he->tag = dm->ntag;
1761  xx = headerGet(pkg->header, he, 0);
1762  if (!xx || he->p.str == NULL)
1763  continue;
1764  xx = strcmp(he->p.str, "/bin/sh") && strcmp(he->p.str, "/bin/bash");
1765  he->p.ptr = _free(he->p.ptr);
1766  if (xx)
1767  continue;
1768 
1769  /* Retrieve scriptlet body. */
1770  he->tag = dm->vtag;
1771  xx = headerGet(pkg->header, he, 0);
1772  if (!xx || he->p.str == NULL)
1773  continue;
1774  iob_stdin = rpmiobEmpty(iob_stdin);
1775  iob_stdin = rpmiobAppend(iob_stdin, he->p.str, 1);
1776  iob_stdin = rpmiobRTrim(iob_stdin);
1777  he->p.ptr = _free(he->p.ptr);
1778 
1779  xx = rpmfcExec(dm->argv, iob_stdin, &iob_stdout, failnonzero);
1780  if (xx == -1)
1781  continue;
1782 
1783  /* Parse dependencies into header */
1784  s = rpmiobStr(iob_stdout);
1785  if (s != NULL && *s != '\0') {
1786  char * se = s;
1787  /* XXX Convert "executable(/path/to/file)" to "/path/to/file". */
1788  while ((se = strstr(se, "executable(/")) != NULL) {
1789 /*@-modobserver@*/ /* FIX: rpmiobStr should not be observer */
1790  se = stpcpy(se, " ");
1791  *se = '/'; /* XXX stpcpy truncates the '/' */
1792 /*@=modobserver@*/
1793  se = strchr(se, ')');
1794  if (se == NULL)
1795  /*@innerbreak@*/ break;
1796  *se++ = ' ';
1797  }
1798  if (spec->_parseRCPOT)
1799  rc = spec->_parseRCPOT(spec, pkg, s, tag, 0, tagflags);
1800  }
1801  iob_stdout = rpmiobFree(iob_stdout);
1802 
1803  }
1804 
1805  iob_stdin = rpmiobFree(iob_stdin);
1806 
1807  return rc;
1808 }
1809 
1810 static unsigned removeSillyDeps(Header h, rpmfc fc) {
1811  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1812  int xx;
1813  unsigned i, rnum, removed = 0;
1814  const char **deps = NULL;
1815  const char **versions = NULL;
1816  evrFlags *flags = NULL;
1817  int *newpos = NULL, *ddictxPos = NULL;
1818 
1819  he->tag = RPMTAG_REQUIRENAME;
1820  xx = headerGet(h, he, 0);
1821  deps = he->p.argv;
1822  rnum = he->c;
1823 
1824  he->tag = RPMTAG_REQUIREVERSION;
1825  xx = headerGet(h, he, 0);
1826  versions = he->p.argv;
1827 
1828  he->tag = RPMTAG_REQUIREFLAGS;
1829  xx = headerGet(h, he, 0);
1830  flags = (evrFlags*)he->p.ui32p;
1831 
1832  if (fc && fc->requires != NULL && fc->ddictx != NULL) {
1833  newpos = alloca(he->c*sizeof(newpos[0]));
1834  if (fc->ddictx)
1835  ddictxPos = alloca(fc->ddictx->nvals*sizeof(ddictxPos[0]));
1836  }
1837  for (i = 0; i < rnum-removed; i++) {
1838  if (removed) {
1839  deps[i] = deps[i+removed];
1840  versions[i] = versions[i+removed];
1841  flags[i] = flags[i+removed];
1842  if (fc) {
1843  fc->requires->N[i] = fc->requires->N[i+removed];
1844  fc->requires->EVR[i] = fc->requires->EVR[i+removed];
1845  fc->requires->Flags[i] = fc->requires->Flags[i+removed];
1846  }
1847  }
1848  if (fc && fc->requires != NULL && fc->ddictx != NULL)
1849  newpos[i+removed] = i;
1850  rpmds req = rpmdsSingle(RPMTAG_REQUIRENAME, deps[i], versions[i], flags[i]);
1851  rpmds prov = rpmdsNew(h, (*deps[i] == '/' && !*versions[i]) ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME, 0);
1852  if (rpmdsMatch(req, prov)) {
1853  if (flags[i] & RPMSENSE_SCRIPT_PRE)
1854  rpmlog(RPMLOG_ERR, "Requires(pre): on dependency provided by self: %s\n", rpmdsDNEVR(req));
1855  else {
1856  if (fc && fc->requires != NULL && fc->ddictx != NULL)
1857  newpos[i+removed] = -1;
1858  rpmlog(RPMLOG_NOTICE, "Removing dependency on self: %s\n", rpmdsDNEVR(req));
1859  removed++;
1860  i--;
1861  }
1862  }
1863  req = rpmdsFree(req);
1864  prov = rpmdsFree(prov);
1865  }
1866  if (fc && fc->requires != NULL && fc->ddictx != NULL && removed) {
1867  fc->requires->Count -= removed;
1868  unsigned rx = 0;
1869  for (i = 0; i < fc->ddictx->nvals-rx; i++) {
1870  unsigned ix;
1871  unsigned char deptype;
1872 
1873  ix = fc->ddictx->vals[i+rx];
1874  deptype = ((ix >> 24) & 0xff);
1875  ix &= 0x00ffffff;
1876 
1877  if (deptype == 'P') {
1878  ddictxPos[i+rx] = i;
1879  fc->ddictx->vals[i] = fc->ddictx->vals[i+rx];
1880  continue;
1881  }
1882  if (newpos[ix] == -1) {
1883  ddictxPos[i+rx] = -1;
1884  i--, rx++;
1885  }
1886  else
1887  {
1888  ddictxPos[i+rx] = i;
1889  fc->ddictx->vals[i] = (deptype << 24) | (newpos[ix] & 0x00ffffff);
1890  }
1891  }
1892  fc->ddictx->nvals -= rx;
1893 
1894  for (i = 0; i < fc->fddictn->nvals; i++) {
1895  rx = 0;
1896  if (fc->fddictn->vals[i]) {
1897  unsigned j, ix = fc->fddictx->vals[i];
1898  for (j = 0, rx = 0; j < fc->fddictn->vals[i]; j++, ix++) {
1899  if (ddictxPos[ix] == -1)
1900  rx++;
1901  if (j == 0 || fc->fddictx->vals[i] == -1)
1902  fc->fddictx->vals[i] = ddictxPos[ix];
1903  }
1904  }
1905  if (rx)
1906  fc->fddictn->vals[i] -= rx;
1907  if (fc->fddictn->vals[i] == 0)
1908  fc->fddictx->vals[i] = 0;
1909  }
1910  }
1911 
1912  if (removed) {
1913  he->tag = RPMTAG_REQUIRENAME;
1914  he->t = RPM_STRING_ARRAY_TYPE;
1915  he->p.argv = deps;
1916  he->c -= removed;
1917  headerMod(h, he, 0);
1918 
1919  he->tag = RPMTAG_REQUIREVERSION;
1920  he->p.argv = versions;
1921  headerMod(h, he, 0);
1922 
1923  he->tag = RPMTAG_REQUIREFLAGS;
1924  he->t = RPM_UINT32_TYPE;
1925  he->p.ui32p = (uint32_t*)flags;
1926  headerMod(h, he, 0);
1927  }
1928 
1929  return removed;
1930 }
1931 
1932 rpmRC rpmfcGenerateDepends(void * _spec, void * _pkg)
1933 {
1934  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1935  const Spec spec = (Spec) _spec;
1936  Package pkg = (Package) _pkg;
1937  rpmfi fi = pkg->fi;
1938  rpmfc fc = NULL;
1939  rpmds ds;
1940  int flags = 0x2; /* XXX no filtering, !scareMem */
1941  ARGV_t av;
1942  rpmuint16_t * fmode;
1943  int ac = rpmfiFC(fi);
1944  char buf[BUFSIZ];
1945  const char * N;
1946  const char * EVR;
1947  int genConfigDeps, internaldeps;
1948  rpmRC rc = RPMRC_OK;
1949  int i;
1950  int xx;
1951 
1952  /* Skip packages with no files. */
1953  if (ac <= 0)
1954  return RPMRC_OK;
1955 
1956  /* Skip packages that have dependency generation disabled. */
1957  if (! (pkg->autoReq || pkg->autoProv))
1958  return RPMRC_OK;
1959 
1960  /* If new-fangled dependency generation is disabled ... */
1961  internaldeps = rpmExpandNumeric("%{?_use_internal_dependency_generator}");
1962  if (internaldeps == 0) {
1963  /* ... then generate dependencies using %{__find_requires} et al. */
1964  rc = rpmfcGenerateDependsHelper(spec, pkg, fi);
1965  removeSillyDeps(pkg->header, NULL);
1966  printDeps(pkg->header);
1967  return rc;
1968  }
1969 
1970  /* Generate scriptlet Dependencies. */
1971  if (internaldeps > 1)
1972  xx = rpmfcGenerateScriptletDeps(spec, pkg);
1973 
1974  /* Extract absolute file paths in argv format. */
1975  /* XXX TODO: should use argvFoo ... */
1976  av = (ARGV_t) xcalloc(ac+1, sizeof(*av));
1977  fmode = (rpmuint16_t *) xcalloc(ac+1, sizeof(*fmode));
1978 
1979  genConfigDeps = 0;
1980  fi = rpmfiInit(fi, 0);
1981  if (fi != NULL)
1982  while ((i = rpmfiNext(fi)) >= 0) {
1983  rpmfileAttrs fileAttrs;
1984 
1985  /* Does package have any %config files? */
1986  fileAttrs = (rpmfileAttrs) rpmfiFFlags(fi);
1987  genConfigDeps |= (fileAttrs & RPMFILE_CONFIG);
1988 
1989  av[i] = xstrdup(rpmfiFN(fi));
1990  fmode[i] = rpmfiFMode(fi);
1991  }
1992  av[ac] = NULL;
1993 
1994  fc = rpmfcNew();
1995  fc->skipProv = !pkg->autoProv;
1996  fc->skipReq = !pkg->autoReq;
1997  fc->tracked = 0;
1998 
1999  { const char * buildRootURL;
2000  const char * buildRoot;
2001  buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
2002  (void) urlPath(buildRootURL, &buildRoot);
2003  if (buildRoot && !strcmp(buildRoot, "/")) buildRoot = NULL;
2004  fc->brlen = (buildRoot ? strlen(buildRoot) : 0);
2005  buildRootURL = _free(buildRootURL);
2006  }
2007 
2008  /* Copy (and delete) manually generated dependencies to dictionary. */
2009  if (!fc->skipProv) {
2010  ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, flags);
2011  xx = rpmdsMerge(&fc->provides, ds);
2012  (void)rpmdsFree(ds);
2013  ds = NULL;
2014  he->tag = RPMTAG_PROVIDENAME;
2015  xx = headerDel(pkg->header, he, 0);
2016  he->tag = RPMTAG_PROVIDEVERSION;
2017  xx = headerDel(pkg->header, he, 0);
2018  he->tag = RPMTAG_PROVIDEFLAGS;
2019  xx = headerDel(pkg->header, he, 0);
2020 
2021  /* Add config dependency, Provides: config(N) = EVR */
2022  if (genConfigDeps) {
2023  static evrFlags _Flags = (evrFlags)(RPMSENSE_EQUAL|RPMSENSE_CONFIG);
2024  N = rpmdsN(pkg->ds);
2025 assert(N != NULL);
2026  EVR = rpmdsEVR(pkg->ds);
2027 assert(EVR != NULL);
2028  sprintf(buf, "config(%s)", N);
2029  ds = rpmdsSingle(RPMTAG_PROVIDENAME, buf, EVR, _Flags);
2030  xx = rpmdsMerge(&fc->provides, ds);
2031  (void)rpmdsFree(ds);
2032  ds = NULL;
2033  }
2034  }
2035 
2036  if (!fc->skipReq) {
2037  ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, flags);
2038  xx = rpmdsMerge(&fc->requires, ds);
2039  (void)rpmdsFree(ds);
2040  ds = NULL;
2041  he->tag = RPMTAG_REQUIRENAME;
2042  xx = headerDel(pkg->header, he, 0);
2043  he->tag = RPMTAG_REQUIREVERSION;
2044  xx = headerDel(pkg->header, he, 0);
2045  he->tag = RPMTAG_REQUIREFLAGS;
2046  xx = headerDel(pkg->header, he, 0);
2047 
2048  /* Add config dependency, Requires: config(N) = EVR */
2049  if (genConfigDeps) {
2050  static evrFlags _Flags = (evrFlags)(RPMSENSE_EQUAL|RPMSENSE_CONFIG);
2051  N = rpmdsN(pkg->ds);
2052 assert(N != NULL);
2053  EVR = rpmdsEVR(pkg->ds);
2054 assert(EVR != NULL);
2055  sprintf(buf, "config(%s)", N);
2056  ds = rpmdsSingle(RPMTAG_REQUIRENAME, buf, EVR, _Flags);
2057  xx = rpmdsMerge(&fc->requires, ds);
2058  (void)rpmdsFree(ds);
2059  ds = NULL;
2060  }
2061  }
2062 
2063  /* Build file class dictionary. */
2064  xx = rpmfcClassify(fc, av, fmode);
2065 
2066  /* Build file/package dependency dictionary. */
2067  xx = rpmfcApply(fc);
2068 
2069  /* Add per-file colors(#files) */
2070  he->tag = RPMTAG_FILECOLORS;
2071  he->t = RPM_UINT32_TYPE;
2072  he->p.ui32p = argiData(fc->fcolor);
2073  he->c = argiCount(fc->fcolor);
2074 assert(ac == (int)he->c);
2075  if (he->p.ptr != NULL && he->c > 0) {
2076  rpmuint32_t * fcolors = he->p.ui32p;
2077 
2078  /* XXX Make sure only primary (i.e. Elf32/Elf64) colors are added. */
2079  for (i = 0; i < (int)he->c; i++)
2080  fcolors[i] &= 0x0f;
2081 
2082  xx = headerPut(pkg->header, he, 0);
2083  }
2084 
2085  /* Add classes(#classes) */
2086  he->tag = RPMTAG_CLASSDICT;
2087  he->t = RPM_STRING_ARRAY_TYPE;
2088  he->p.argv = argvData(fc->cdict);
2089  he->c = argvCount(fc->cdict);
2090  if (he->p.ptr != NULL && he->c > 0) {
2091  xx = headerPut(pkg->header, he, 0);
2092  }
2093 
2094  /* Add per-file classes(#files) */
2095  he->tag = RPMTAG_FILECLASS;
2096  he->t = RPM_UINT32_TYPE;
2097  he->p.ui32p = argiData(fc->fcdictx);
2098  he->c = argiCount(fc->fcdictx);
2099 assert(ac == (int)he->c);
2100  if (he->p.ptr != NULL && he->c > 0) {
2101  xx = headerPut(pkg->header, he, 0);
2102  }
2103 
2104  /* Add Provides: */
2105  if (fc->provides != NULL && (he->c = rpmdsCount(fc->provides)) > 0
2106  && !fc->skipProv)
2107  {
2108  he->tag = RPMTAG_PROVIDENAME;
2109  he->t = RPM_STRING_ARRAY_TYPE;
2110  he->p.argv = fc->provides->N;
2111  xx = headerPut(pkg->header, he, 0);
2112 
2113  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
2114 /*@-nullpass@*/
2115  he->tag = RPMTAG_PROVIDEVERSION;
2116  he->t = RPM_STRING_ARRAY_TYPE;
2117  he->p.argv = fc->provides->EVR;
2118 assert(he->p.ptr != NULL);
2119  xx = headerPut(pkg->header, he, 0);
2120 
2121  he->tag = RPMTAG_PROVIDEFLAGS;
2122  he->t = RPM_UINT32_TYPE;
2123  he->p.ui32p = (rpmuint32_t *) fc->provides->Flags;
2124 assert(he->p.ptr != NULL);
2125  xx = headerPut(pkg->header, he, 0);
2126 /*@=nullpass@*/
2127  }
2128 
2129  /* Add Requires: */
2130  if (fc->requires != NULL && (he->c = rpmdsCount(fc->requires)) > 0
2131  && !fc->skipReq)
2132  {
2133  he->tag = RPMTAG_REQUIRENAME;
2134  he->t = RPM_STRING_ARRAY_TYPE;
2135  he->p.argv = fc->requires->N;
2136 assert(he->p.ptr != NULL);
2137  xx = headerPut(pkg->header, he, 0);
2138 
2139  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
2140 /*@-nullpass@*/
2141  he->tag = RPMTAG_REQUIREVERSION;
2142  he->t = RPM_STRING_ARRAY_TYPE;
2143  he->p.argv = fc->requires->EVR;
2144 assert(he->p.ptr != NULL);
2145  xx = headerPut(pkg->header, he, 0);
2146 
2147  he->tag = RPMTAG_REQUIREFLAGS;
2148  he->t = RPM_UINT32_TYPE;
2149  he->p.ui32p = (rpmuint32_t *) fc->requires->Flags;
2150 assert(he->p.ptr != NULL);
2151  xx = headerPut(pkg->header, he, 0);
2152 /*@=nullpass@*/
2153  }
2154 
2155  removeSillyDeps(pkg->header, fc);
2156 
2157  /* Add dependency dictionary(#dependencies) */
2158  he->tag = RPMTAG_DEPENDSDICT;
2159  he->t = RPM_UINT32_TYPE;
2160  he->p.ui32p = argiData(fc->ddictx);
2161  he->c = argiCount(fc->ddictx);
2162  if (he->p.ptr != NULL) {
2163  xx = headerPut(pkg->header, he, 0);
2164  }
2165 
2166  /* Add per-file dependency (start,number) pairs (#files) */
2167  he->tag = RPMTAG_FILEDEPENDSX;
2168  he->t = RPM_UINT32_TYPE;
2169  he->p.ui32p = argiData(fc->fddictx);
2170  he->c = argiCount(fc->fddictx);
2171 assert(ac == (int)he->c);
2172  if (he->p.ptr != NULL) {
2173  xx = headerPut(pkg->header, he, 0);
2174  }
2175 
2176  he->tag = RPMTAG_FILEDEPENDSN;
2177  he->t = RPM_UINT32_TYPE;
2178  he->p.ui32p = argiData(fc->fddictn);
2179  he->c = argiCount(fc->fddictn);
2180 assert(ac == (int)he->c);
2181  if (he->p.ptr != NULL) {
2182  xx = headerPut(pkg->header, he, 0);
2183  }
2184 
2185  printDeps(pkg->header);
2186 
2187 if (fc != NULL && _rpmfc_debug) {
2188 char msg[BUFSIZ];
2189 sprintf(msg, "final: files %u cdict[%d] %u%% ddictx[%d]", (unsigned int)fc->nfiles, argvCount(fc->cdict), (unsigned int)((100 * fc->fknown)/fc->nfiles), argiCount(fc->ddictx));
2190 rpmfcPrint(msg, fc, NULL);
2191 }
2192 
2193  /* Clean up. */
2194  fmode = _free(fmode);
2195  fc = rpmfcFree(fc);
2196  av = argvFree(av);
2197 
2198  return rc;
2199 }
2200 
2201 /*@-mustmod@*/
2202 static void rpmfcFini(void * _fc)
2203  /*@modifies _fc @*/
2204 {
2205  rpmfc fc = (rpmfc) _fc;
2206 
2207  fc->fn = argvFree(fc->fn);
2208  fc->fcolor = argiFree(fc->fcolor);
2209  fc->fcdictx = argiFree(fc->fcdictx);
2210  fc->fddictx = argiFree(fc->fddictx);
2211  fc->fddictn = argiFree(fc->fddictn);
2212  fc->cdict = argvFree(fc->cdict);
2213  fc->ddict = argvFree(fc->ddict);
2214  fc->ddictx = argiFree(fc->ddictx);
2215 
2216  (void)rpmdsFree(fc->provides);
2217  fc->provides = NULL;
2218  (void)rpmdsFree(fc->requires);
2219  fc->requires = NULL;
2220 
2221  fc->iob_java = rpmiobFree(fc->iob_java);
2222  fc->iob_perl = rpmiobFree(fc->iob_perl);
2223  fc->iob_python = rpmiobFree(fc->iob_python);
2224  fc->iob_php = rpmiobFree(fc->iob_php);
2225 }
2226 /*@=mustmod@*/
2227 
2228 /*@unchecked@*/ /*@only@*/ /*@null@*/
2230 
2231 static rpmfc rpmfcGetPool(/*@null@*/ rpmioPool pool)
2232  /*@globals _rpmfcPool, fileSystem, internalState @*/
2233  /*@modifies pool, _rpmfcPool, fileSystem, internalState @*/
2234 {
2235  rpmfc fc;
2236 
2237  if (_rpmfcPool == NULL) {
2238  _rpmfcPool = rpmioNewPool("fc", sizeof(*fc), -1, _rpmfc_debug,
2239  NULL, NULL, rpmfcFini);
2240  pool = _rpmfcPool;
2241  }
2242  fc = (rpmfc) rpmioGetPool(pool, sizeof(*fc));
2243  memset(((char *)fc)+sizeof(fc->_item), 0, sizeof(*fc)-sizeof(fc->_item));
2244  return fc;
2245 }
2246 
2248 {
2249  rpmfc fc = rpmfcGetPool(_rpmfcPool);
2250  fc->fn = (ARGV_t) xcalloc(1, sizeof(*fc->fn));
2251  return rpmfcLink(fc);
2252 }
2253 
rpmuint32_t rpmfiFFlags(rpmfi fi)
Return current file flags from file info set.
Definition: rpmfi.c:217
rpmds rpmdsSingle(rpmTag tagN, const char *N, const char *EVR, evrFlags Flags)
Create, load and initialize a dependency set of size 1.
Definition: rpmds.c:609
rpmTagType t
Definition: rpmtag.h:504
evrFlags rpmdsFlags(const rpmds ds)
Return current dependency flags.
Definition: rpmds.c:691
rpmiob rpmiobRTrim(rpmiob iob)
Trim trailing white space.
Definition: rpmiob.c:67
const char * str
Definition: rpmtag.h:73
rpmTag tag
Definition: rpmtag.h:503
const char ** argv
Definition: rpmtag.h:75
rpmds rpmdsInit(rpmds ds)
Initialize dependency set iterator.
Definition: rpmds.c:943
miRE mireNew(rpmMireMode mode, int tag)
Create pattern container.
Definition: mire.c:113
const char * rpmmgFile(rpmmg mg, const char *fn)
Return magic string for a file.
Definition: rpmmg.c:84
static struct rpmfcApplyTbl_s rpmfcApplyTable[]
XXX Having two entries for rpmfcSCRIPT may be unnecessary duplication.
Definition: rpmfc.c:1086
#define RPMELF_FLAG_SKIPREQUIRES
Definition: rpmds.h:621
static DepMsg_t ScriptMsgs
Definition: rpmfc.c:1735
ARGI_t argiFree(ARGI_t argi)
Destroy an argi array.
Definition: argv.c:34
void * mireFreeAll(miRE mire, int nmire)
Destroy compiled patterns.
Definition: mire.c:96
enum urltype_e urltype
Supported URL types.
static void rpmfcFini(void *_fc)
Definition: rpmfc.c:2202
static int rpmfcMatchRegexps(void *_mire, int nmire, const char *str, char deptype)
Definition: rpmfc.c:377
const char const char * cmd
Definition: mongo.h:777
struct DepMsg_s * DepMsg_t
Definition: rpmfc.c:1521
#define EXIT_FAILURE
static void printDeps(Header h)
Print dependencies in a header.
Definition: rpmfc.c:1586
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
size_t rpmiobLen(rpmiob iob)
Return I/O buffer len.
Definition: rpmiob.c:122
rpmuint32_t * ui32p
Definition: rpmtag.h:70
static int rpmfcExpandAppend(ARGV_t *argvp, const ARGV_t av)
Definition: rpmfc.c:45
const char * rootURL
Definition: rpmspec.h:120
Structure(s) used for file info tag sets.
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2231
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2294
The Header data structure.
int mireRegcomp(miRE mire, const char *pattern)
Compile pattern match.
Definition: mire.c:332
int argvAppend(ARGV_t *argvp, ARGV_t av)
Append one argv array to another.
Definition: argv.c:216
Structure(s) and routine(s) used for classifying and parsing names.
static int rpmfcELF(rpmfc fc)
Extract Elf dependencies.
Definition: rpmfc.c:1030
int errno
rpmTag rpmdsTagN(const rpmds ds)
Return current dependency type.
Definition: rpmds.c:702
int headerDel(Header h, HE_t he, unsigned int flags)
Remove tag container from header.
Definition: header.c:2313
const char * rpmfiFN(rpmfi fi)
Return current file name from file info set.
Definition: rpmfi.c:163
unsigned short rpmuint16_t
Definition: rpmiotypes.h:27
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
int rpmEVRparse(const char *evrstr, EVR_t evr)
Split EVR string into epoch, version, and release components.
Definition: rpmevr.c:181
struct EVR_s * EVR_t
Definition: rpmevr.h:22
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
rpmRC rpmfcApply(rpmfc fc)
Build file/package dependency dictionary and mappings.
Definition: rpmfc.c:1096
const char * rpmdsDNEVR(const rpmds ds)
Return current formatted dependency string.
Definition: rpmds.c:657
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:77
static int rpmfcSaveArg(ARGV_t *argvp, const char *key)
Definition: rpmfc.c:289
struct rpmds_s * rpmds
Dependency tag sets from a header, so that a header can be discarded early.
Definition: rpmtypes.h:28
static rpmiob getOutputFrom(const char *dir, ARGV_t argv, const char *writePtr, size_t writeBytesLeft, int failNonZero)
Return output from helper script.
Definition: rpmfc.c:79
int argiCount(ARGI_t argi)
Return no.
Definition: argv.c:55
rpmds rpmdsFree(rpmds ds)
Destroy a dependency set.
int rpmfiFC(rpmfi fi)
Return file count from file info set.
Definition: rpmfi.c:87
int rpmEVRcompare(const EVR_t a, const EVR_t b)
Compare EVR containers for equality.
Definition: rpmevr.c:280
char * argvJoin(ARGV_t argv, char sep)
Concatenate an argv array into a string.
Definition: argv.c:274
enum evrFlags_e evrFlags
Dependency Attributes.
int toggle
Definition: rpmfc.c:1534
char * alloca()
const char * str
Definition: bson.h:593
Yet Another syslog(3) API clone.
int headerMod(Header h, HE_t he, unsigned int flags)
Modify tag container in header.
Definition: header.c:2319
static struct rpmfcTokens_s rpmfcTokens[]
Definition: rpmfc.c:572
Header header
Definition: rpmspec.h:217
static rpmfc rpmfcGetPool(rpmioPool pool)
Definition: rpmfc.c:2231
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
struct _HE_s * HE_t
Definition: rpmtag.h:59
miRE mireFree(miRE mire)
Free pattern container.
const char * argv[4]
Definition: rpmfc.c:1529
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
void * ptr
Definition: rpmtag.h:67
rpmfc rpmfcLink(rpmfc fc)
Reference a file classifier instance.
const char * mode
Definition: mongo.h:440
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
rpmfc rpmfcFree(rpmfc fc)
Destroy a file classifier.
rpmTag vtag
Definition: rpmfc.c:1531
static DepMsg_t DepMsgs
Definition: rpmfc.c:1580
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:83
RPM pattern matching.
int argvCount(const ARGV_t argv)
Return no.
Definition: argv.c:71
rpmuint16_t rpmfiFMode(rpmfi fi)
Return current file mode from file info set.
Definition: rpmfi.c:265
ARGV_t argvData(ARGV_t argv)
Return data from argv array.
Definition: argv.c:80
int rpmdsFind(rpmds ds, const rpmds ods)
Find a dependency set element using binary search.
Definition: rpmds.c:998
enum evrFlags_e rpmsenseFlags
Definition: rpmevr.h:74
rpmTagData p
Definition: rpmtag.h:506
static int rpmfcMergePR(void *context, rpmds ds)
Merge provides/requires dependencies into a rpmfc container.
Definition: rpmfc.c:981
static unsigned removeSillyDeps(Header h, rpmfc fc)
Definition: rpmfc.c:1810
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
struct miRE_s * miRE
Definition: mire.h:60
int _rpmfc_debug
Definition: poptALL.c:123
int rpmfcExec(ARGV_t av, rpmiob iob_stdin, rpmiob *iob_stdoutp, int failnonzero)
Definition: rpmfc.c:229
const char * rpmdsEVR(const rpmds ds)
Return current dependency epoch-version-release.
Definition: rpmds.c:680
const char * tagName(rpmTag tag)
Return tag name from value.
Definition: tagname.c:436
const char * msg
Definition: rpmfc.c:1527
static int _filter_values
Definition: rpmfc.c:39
int rpmdsNext(rpmds ds)
Return next dependency set iterator index.
Definition: rpmds.c:912
Structure(s) used for dependency tag sets.
static const char * ftype(unsigned type)
Definition: rpmmtree.c:1701
int autoProv
Definition: rpmspec.h:224
rpmTag ftag
Definition: rpmfc.c:1532
struct Spec_s * Spec
Definition: rpmtypes.h:23
rpmRC(* _parseRCPOT)(Spec spec, Package pkg, const char *field, rpmTag tagN, rpmuint32_t index, rpmsenseFlags tagflags)
Definition: rpmspec.h:179
const char * rpmGenPath(const char *urlroot, const char *urlmdir, const char *urlfile)
Merge 3 args into path, any or all of which may be a url.
Definition: macro.c:3491
int argvAdd(ARGV_t *argvp, ARGstr_t val)
Add a string to an argv array.
Definition: argv.c:199
rpmTagCount c
Definition: rpmtag.h:507
int mireRegexec(miRE mire, const char *val, size_t vallen)
Execute pattern match.
Definition: mire.c:396
rpmmg rpmmgNew(const char *fn, int flags)
Create and load a magic wrapper.
Definition: rpmmg.c:57
The structure used to store values parsed from a spec file.
Definition: rpmspec.h:113
static char * rpmfcFileDep(char *buf, size_t ix, rpmds ds)
Definition: rpmfc.c:304
struct rpmfcApplyTbl_s * rpmfcApplyTbl
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3252
static struct DepMsg_s scriptMsgs[]
Definition: rpmfc.c:1717
int Chdir(const char *path)
chdir(2) clone.
Definition: rpmrpc.c:105
int rpmdsCount(const rpmds ds)
Return dependency set count.
Definition: rpmds.c:636
void rpmfcPrint(const char *msg, rpmfc fc, FILE *fp)
Print results of file classification.
Definition: rpmfc.c:698
struct Package_s * Package
Definition: rpmspec.h:20
int(* func)(rpmfc fc)
Definition: rpmfc.c:1077
void unsetenv(const char *name)
static int rpmfcHelper(rpmfc fc, unsigned char deptype, const char *nsdep)
Run per-interpreter dependency helper.
Definition: rpmfc.c:414
static struct DepMsg_s depMsgs[]
Definition: rpmfc.c:1541
const char * rpmdsN(const rpmds ds)
Return current dependency name.
Definition: rpmds.c:668
static int rpmfcSCRIPT(rpmfc fc)
Extract script dependencies.
Definition: rpmfc.c:780
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
enum rpmfileAttrs_e rpmfileAttrs
File Attributes.
int rpmfiNext(rpmfi fi)
Return next file iterator index.
Definition: rpmfi.c:526
EVR_t rpmEVRnew(uint32_t Flags, int initialize)
Create a new EVR container.
Definition: rpmevr.c:31
#define S_IFSOCK
Definition: system.h:647
enum rpmRC_e rpmRC
RPM return codes.
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:112
Definition: rpmtag.h:502
rpmfi rpmfiInit(rpmfi fi, int fx)
Initialize file iterator index.
Definition: rpmfi.c:548
EVR_t rpmEVRfree(EVR_t evr)
Destroy an EVR container.
Definition: rpmevr.c:47
const char const int i
Definition: bson.h:778
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
int rpmfcColoring(const char *fmstr)
Return file color given file(1) string.
Definition: rpmfc.c:679
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
const char const bson * key
Definition: mongo.h:717
This is the only module users of librpmbuild should need to include.
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpmuint16_t *fmode)
Definition: rpmfc.c:1361
int rpmdsMerge(rpmds *dsp, rpmds ods)
Merge a dependency set maintaining (N,EVR,Flags) sorted order.
Definition: rpmds.c:1030
char * stpcpy(char *dest, const char *src)
struct rpmmg_s * rpmmg
Definition: rpmmg.h:15
static rpmRC rpmfcGenerateDependsHelper(const Spec spec, Package pkg, rpmfi fi)
Definition: rpmfc.c:1634
static int rpmfcGenerateScriptletDeps(const Spec spec, Package pkg)
Definition: rpmfc.c:1739
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:60
#define _suffix(_s, _x)
rpmfi fi
Definition: filetriggers.h:15
rpmds ds
Definition: rpmspec.h:219
int argiAdd(ARGI_t *argip, int ix, int val)
Add an int to an argi array.
Definition: argv.c:178
rpmioPool _rpmfcPool
Definition: rpmfc.c:2229
int mask
Definition: rpmfc.c:1533
int rpmdsSearch(rpmds ds, rpmds ods)
Search a sorted dependency set for an element that overlaps.
Definition: rpmds.c:1108
int argvSplit(ARGV_t *argvp, const char *str, const char *seps)
Split a string into an argv array.
Definition: argv.c:233
ARGV_t argvSearch(ARGV_t argv, ARGstr_t val, int(*compar)(ARGstr_t *, ARGstr_t *))
Find an element in an argv array.
Definition: argv.c:146
rpmiob rpmiobEmpty(rpmiob iob)
Empty an I/O buffer.
Definition: rpmiob.c:57
int rpmdsMatch(const rpmds A, rpmds B)
Compare A against every member of B, looking for 1st match.
Definition: rpmds.c:4188
struct rpmfcTokens_s * rpmfcToken
Definition: rpmfc.h:15
static void * rpmfcFreeRegexps(void *_mire, int nmire)
Definition: rpmfc.c:398
int argvSort(ARGV_t argv, int(*compar)(ARGstr_t *, ARGstr_t *))
Sort an argv array.
Definition: argv.c:137
int rpmdsELF(const char *fn, int flags, int(*add)(void *context, rpmds ds), void *context)
Return a soname dependency constructed from an elf string.
Definition: rpmds.c:2952
int mireAppend(rpmMireMode mode, int tag, const char *pattern, const unsigned char *table, miRE *mirep, int *nmirep)
Append pattern to array.
Definition: mire.c:497
#define _(Text)
Definition: system.h:29
The structure used to store values for a package.
Definition: rpmspec.h:214
#define RPMELF_FLAG_SKIPPROVIDES
Definition: rpmds.h:620
rpmRC rpmfcGenerateDepends(void *_spec, void *_pkg)
Generate package dependencies.
Definition: rpmfc.c:1932
ARGstr_t * ARGV_t
Definition: argv.h:12
rpmfi fi
Definition: rpmspec.h:221
enum rpmTag_e rpmTag
Definition: rpmtag.h:470
#define D_(Text)
Definition: system.h:526
rpmds rpmdsNew(Header h, rpmTag tagN, int flags)
Create and load a dependency set.
Definition: rpmds.c:238
static int _filter_execs
Definition: rpmfc.c:41
int rpmdsSetIx(rpmds ds, int ix)
Set dependency set index.
Definition: rpmds.c:646
ARGint_t argiData(ARGI_t argi)
Return data from argi array.
Definition: argv.c:63
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3326
struct rpmfc_s * rpmfc
Definition: rpmfc.h:11
#define xrealloc
Definition: system.h:35
rpmmg rpmmgFree(rpmmg mg)
Destroy a magic wrapper.
rpmfc rpmfcNew(void)
Create a file classifier.
Definition: rpmfc.c:2247
#define RPMFC_ELF
Definition: rpmfc.h:25
int autoReq
Definition: rpmspec.h:223
int j
Definition: mongo.h:438
rpmTag ntag
Definition: rpmfc.c:1530
static void * rpmfcExpandRegexps(const char *str, int *nmirep)
Definition: rpmfc.c:334