rpm  5.4.14
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()");
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 
585  { " script", RPMFC_SCRIPT },
586  { " text", RPMFC_TEXT },
587  { " document", RPMFC_DOCUMENT },
588 
589  { " compressed", RPMFC_COMPRESSED },
590 
591  { "troff or preprocessor input", RPMFC_MANPAGE|RPMFC_INCLUDE },
592  { "GNU Info", RPMFC_MANPAGE|RPMFC_INCLUDE },
593 
594  { "Desktop Entry", RPMFC_DESKTOP_FILE|RPMFC_INCLUDE },
595 
596  { "perl script text", RPMFC_PERL|RPMFC_INCLUDE },
597  { "Perl5 module source text", RPMFC_PERL|RPMFC_MODULE|RPMFC_INCLUDE },
598 
599  { "PHP script text", RPMFC_PHP|RPMFC_INCLUDE },
600  { "G-IR binary database", RPMFC_TYPELIB|RPMFC_INCLUDE },
601 
602  /* XXX "a /usr/bin/python -t script text executable" */
603  /* XXX "python 2.3 byte-compiled" */
604  { " /usr/bin/python", RPMFC_PYTHON|RPMFC_INCLUDE },
605  { "python ", RPMFC_PYTHON|RPMFC_INCLUDE },
606  { "Python script", 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  fcolor |= fct->colors;
688  if (fcolor & RPMFC_INCLUDE)
689  return fcolor;
690  }
691  return fcolor;
692 }
693 
694 void rpmfcPrint(const char * msg, rpmfc fc, FILE * fp)
695 {
696  int fcolor;
697  int ndx;
698  int cx;
699  int dx;
700  size_t fx;
701 
702 unsigned nprovides;
703 unsigned nrequires;
704 
705  if (fp == NULL) fp = stderr;
706 
707  if (msg)
708  fprintf(fp, "===================================== %s\n", msg);
709 
710 nprovides = rpmdsCount(fc->provides);
711 nrequires = rpmdsCount(fc->requires);
712 
713  if (fc)
714  for (fx = 0; fx < fc->nfiles; fx++) {
715 assert(fx < fc->fcdictx->nvals);
716  cx = fc->fcdictx->vals[fx];
717 assert(fx < fc->fcolor->nvals);
718  fcolor = fc->fcolor->vals[fx];
719 
720  fprintf(fp, "%3d %s", (int)fx, fc->fn[fx]);
721  if (fcolor != RPMFC_BLACK)
722  fprintf(fp, "\t0x%x", fc->fcolor->vals[fx]);
723  else
724  fprintf(fp, "\t%s", fc->cdict[cx]);
725  fprintf(fp, "\n");
726 
727  if (fc->fddictx == NULL || fc->fddictn == NULL)
728  continue;
729 
730 assert(fx < fc->fddictx->nvals);
731  dx = fc->fddictx->vals[fx];
732 assert(fx < fc->fddictn->nvals);
733  ndx = fc->fddictn->vals[fx];
734 
735  while (ndx-- > 0) {
736  const char * depval;
737  unsigned char deptype;
738  unsigned ix;
739 
740  ix = fc->ddictx->vals[dx++];
741  deptype = ((ix >> 24) & 0xff);
742  ix &= 0x00ffffff;
743  depval = NULL;
744  switch (deptype) {
745  default:
746 assert(depval != NULL);
747  /*@switchbreak@*/ break;
748  case 'P':
749  if (nprovides > 0) {
750 assert(ix < nprovides);
751  (void) rpmdsSetIx(fc->provides, ix-1);
752  if (rpmdsNext(fc->provides) >= 0)
753  depval = rpmdsDNEVR(fc->provides);
754  }
755  /*@switchbreak@*/ break;
756  case 'R':
757  if (nrequires > 0) {
758 assert(ix < nrequires);
759  (void) rpmdsSetIx(fc->requires, ix-1);
760  if (rpmdsNext(fc->requires) >= 0)
761  depval = rpmdsDNEVR(fc->requires);
762  }
763  /*@switchbreak@*/ break;
764  }
765  if (depval)
766  fprintf(fp, "\t%s\n", depval);
767  }
768  }
769 }
770 
776 static int rpmfcSCRIPT(rpmfc fc)
777  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
778  /*@modifies fc, rpmGlobalMacroContext, fileSystem, internalState @*/
779 {
780  const char * fn = fc->fn[fc->ix];
781  const char * bn;
782  rpmds ds;
783  char buf[BUFSIZ];
784  FILE * fp;
785  char * s, * se;
786  int i;
787  int is_executable;
788  int xx;
789 
790  /* Don't generate dependencies from files shipped as documentation */
791  if (!rpmExpandNumeric("%{_generate_dependencies_from_docdir}")) {
792  const char * defaultdocdir = rpmExpand("%{?_defaultdocdir}", NULL);
793  if (defaultdocdir == NULL || *defaultdocdir == '\0')
794  defaultdocdir = strdup("/usr/share/doc");
795  xx = !strncmp(fn+fc->brlen, defaultdocdir, strlen(defaultdocdir));
796  defaultdocdir = _free(defaultdocdir) ;
797  if (xx)
798  return 0;
799  }
800 
801  /* Extract dependencies only from files with executable bit set. */
802  { struct stat sb, * st = &sb;
803  if (stat(fn, st) != 0)
804  return -1;
805  is_executable = (int)(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH));
806  }
807 
808  fp = fopen(fn, "r");
809  if (fp == NULL || ferror(fp)) {
810  if (fp) (void) fclose(fp);
811  return -1;
812  }
813 
814  /* Look for #! interpreter in first 10 lines. */
815  for (i = 0; i < 10; i++) {
816 
817  s = fgets(buf, sizeof(buf) - 1, fp);
818  if (s == NULL || ferror(fp) || feof(fp))
819  break;
820  s[sizeof(buf)-1] = '\0';
821  if (!(s[0] == '#' && s[1] == '!'))
822  continue;
823  s += 2;
824 
825  while (*s && strchr(" \t\n\r", *s) != NULL)
826  s++;
827  if (*s == '\0')
828  continue;
829  if (*s != '/')
830  continue;
831 
832  for (se = s+1; *se; se++) {
833  if (strchr(" \t\n\r", *se) != NULL)
834  /*@innerbreak@*/ break;
835  }
836  *se = '\0';
837  se++;
838 
839  if (!_filter_values
840  || (!fc->skipReq
841  && !rpmfcMatchRegexps(fc->Rmires, fc->Rnmire, s, 'R')))
842  if (is_executable) {
843  /* Add to package requires. */
844  ds = rpmdsSingle(RPMTAG_REQUIRENAME, s, "", RPMSENSE_FIND_REQUIRES);
845  xx = rpmdsMerge(&fc->requires, ds);
846 
847  /* Add to file requires. */
848  xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(se, fc->ix, ds));
849 
850  (void)rpmdsFree(ds);
851  ds = NULL;
852  }
853 
854  /* Set color based on interpreter name. */
855  /* XXX magic token should have already done this?!? */
856 /*@-moduncon@*/
857  bn = basename(s);
858 /*@=moduncon@*/
859  if (!strcmp(bn, "perl"))
860  fc->fcolor->vals[fc->ix] |= RPMFC_PERL;
861  else if (!strncmp(bn, "python", sizeof("python")-1))
862  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
863  else if (!strncmp(bn, "php", sizeof("php")-1))
864  fc->fcolor->vals[fc->ix] |= RPMFC_PHP;
865  else if (!strncmp(bn, "ruby", sizeof("ruby")-1))
866  fc->fcolor->vals[fc->ix] |= RPMFC_RUBY;
867 
868  break;
869  }
870 
871  (void) fclose(fp);
872 
873  if (fc->fcolor->vals[fc->ix] & RPMFC_PERL) {
874  if (fc->fcolor->vals[fc->ix] & RPMFC_MODULE)
875  xx = rpmfcHelper(fc, 'P', "perl");
876  if (is_executable || (fc->fcolor->vals[fc->ix] & RPMFC_MODULE))
877  xx = rpmfcHelper(fc, 'R', "perl");
878  } else
879  if (fc->fcolor->vals[fc->ix] & RPMFC_PYTHON) {
880  xx = rpmfcHelper(fc, 'P', "python");
881 #ifdef NOTYET
882  if (is_executable)
883 #endif
884  xx = rpmfcHelper(fc, 'R', "python");
885  } else
886  if (fc->fcolor->vals[fc->ix] & RPMFC_LIBTOOL) {
887  xx = rpmfcHelper(fc, 'P', "libtool");
888 #ifdef NOTYET
889  if (is_executable)
890 #endif
891  xx = rpmfcHelper(fc, 'R', "libtool");
892  } else
893  if (fc->fcolor->vals[fc->ix] & RPMFC_PKGCONFIG) {
894  xx = rpmfcHelper(fc, 'P', "pkgconfig");
895 #ifdef NOTYET
896  if (is_executable)
897 #endif
898  xx = rpmfcHelper(fc, 'R', "pkgconfig");
899  } else
900  if (fc->fcolor->vals[fc->ix] & RPMFC_BOURNE) {
901 #ifdef NOTYET
902  xx = rpmfcHelper(fc, 'P', "executable");
903 #endif
904  if (is_executable)
905  xx = rpmfcHelper(fc, 'R', "executable");
906  } else
907  if (fc->fcolor->vals[fc->ix] & RPMFC_PHP) {
908  xx = rpmfcHelper(fc, 'P', "php");
909  /* not only executable, files run by httpd usually are not */
910  xx = rpmfcHelper(fc, 'R', "php");
911  } else
912  if (fc->fcolor->vals[fc->ix] & RPMFC_MONO) {
913  xx = rpmfcHelper(fc, 'P', "mono");
914  if (is_executable)
915  xx = rpmfcHelper(fc, 'R', "mono");
916  } else
917  if (fc->fcolor->vals[fc->ix] & RPMFC_RUBY) {
918  xx = rpmfcHelper(fc, 'P', "ruby");
919 #ifdef NOTYET
920  if (is_executable)
921 #endif
922  xx = rpmfcHelper(fc, 'R', "ruby");
923  } else
924  if ((fc->fcolor->vals[fc->ix] & RPMFC_FONT) == RPMFC_FONT) {
925  xx = rpmfcHelper(fc, 'P', "font");
926  /* XXX: currently of no use, but for the sake of consistency... */
927  xx = rpmfcHelper(fc, 'R', "font");
928  } else
929  if (fc->fcolor->vals[fc->ix] & RPMFC_HASKELL) {
930  xx = rpmfcHelper(fc, 'P', "haskell");
931  xx = rpmfcHelper(fc, 'R', "haskell");
932  } else
933  if (fc->fcolor->vals[fc->ix] & RPMFC_TYPELIB) {
934  xx = rpmfcHelper(fc, 'P', "typelib");
935 #ifdef NOTYET
936  if (is_executable)
937 #endif
938  xx = rpmfcHelper(fc, 'R', "typelib");
939  } else
940  if ((fc->fcolor->vals[fc->ix] & (RPMFC_MODULE|RPMFC_LIBRARY)) &&
941  strstr(fn, "/gstreamer")) {
942  xx = rpmfcHelper(fc, 'P', "gstreamer");
943  /* XXX: currently of no use, but for the sake of consistency... */
944  xx = rpmfcHelper(fc, 'R', "gstreamer");
945 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_PLD)
946  } else
947  if ((fc->fcolor->vals[fc->ix] & RPMFC_MODULE)) {
949  if (!mireRegcomp(mire, "^.*((/lib/modules/|/var/lib/dkms/).*\\.ko(\\.gz|\\.xz)?|(/var/lib/dkms-binary/[^/]+/[^/]+|/usr/src)/[^/]+/dkms.conf)$"))
950  if (mireRegexec(mire, fc->fn[fc->ix], (size_t) 0) >= 0) {
951  fc->fcolor->vals[fc->ix] |= (RPMFC_MODULE|RPMFC_SCRIPT);
952  xx = rpmfcHelper(fc, 'P', "kernel");
953  /* XXX: currently of no use, but for the sake of consistency... */
954  xx = rpmfcHelper(fc, 'R', "kernel");
955  }
956  mire = mireFree(mire);
957 #endif
958  } else
959  if (fc->fcolor->vals[fc->ix] & RPMFC_JAVA) {
960  xx = rpmfcHelper(fc, 'P', "java");
961  xx = rpmfcHelper(fc, 'R', "java");
962  } else
963  if (fc->fcolor->vals[fc->ix] & RPMFC_DESKTOP_FILE) {
964  xx = rpmfcHelper(fc, 'P', "mimetype");
965  }
966 
967 /*@=observertrans@*/
968  return 0;
969 }
970 
977 static int rpmfcMergePR(void * context, rpmds ds)
978  /*@globals fileSystem, internalState @*/
979  /*@modifies ds, fileSystem, internalState @*/
980 {
981  rpmfc fc = (rpmfc) context;
982  char buf[BUFSIZ];
983  int rc = 0;
984 
985 if (_rpmfc_debug < 0)
986 fprintf(stderr, "*** rpmfcMergePR(%p, %p) %s\n", context, ds, tagName(rpmdsTagN(ds)));
987  switch(rpmdsTagN(ds)) {
988  default:
989  rc = -1;
990  break;
991  case RPMTAG_PROVIDENAME:
992  if (!_filter_values
993  || (!fc->skipProv
994  && !rpmfcMatchRegexps(fc->Pmires, fc->Pnmire, ds->N[0], 'P')))
995  {
996  /* Add to package provides. */
997  rc = rpmdsMerge(&fc->provides, ds);
998 
999  /* Add to file dependencies. */
1000  buf[0] = '\0';
1001  rc = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
1002  }
1003  break;
1004  case RPMTAG_REQUIRENAME:
1005  if (!_filter_values
1006  || (!fc->skipReq
1007  && !rpmfcMatchRegexps(fc->Rmires, fc->Rnmire, ds->N[0], 'R')))
1008  {
1009  /* Add to package requires. */
1010  rc = rpmdsMerge(&fc->requires, ds);
1011 
1012  /* Add to file dependencies. */
1013  buf[0] = '\0';
1014  rc = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, ds));
1015  }
1016  break;
1017  }
1018  return rc;
1019 }
1020 
1026 static int rpmfcELF(rpmfc fc)
1027  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1028  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
1029 {
1030  const char * fn = fc->fn[fc->ix];
1031  int flags = 0;
1032 
1033  if (fc->skipProv)
1034  flags |= RPMELF_FLAG_SKIPPROVIDES;
1035  if (fc->skipReq)
1036  flags |= RPMELF_FLAG_SKIPREQUIRES;
1037 
1038  return rpmdsELF(fn, flags, rpmfcMergePR, fc);
1039 }
1040 
1041 #if defined(RPM_VENDOR_MANDRIVA)
1042 
1051 extern int rpmdsSymlink(const char * fn, int flags,
1052  int (*add) (void * context, rpmds ds), void * context)
1053  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1054  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/;
1055 
1056 static int rpmfcSYMLINK(rpmfc fc)
1057  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1058  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
1059 {
1060  const char * fn = fc->fn[fc->ix];
1061  int flags = 0;
1062 
1063  if (fc->skipProv)
1064  flags |= RPMELF_FLAG_SKIPPROVIDES;
1065  if (fc->skipReq)
1066  flags |= RPMELF_FLAG_SKIPREQUIRES;
1067 
1068  return rpmdsSymlink(fn, flags, rpmfcMergePR, fc);
1069 }
1070 #endif /* RPM_VENDOR_MANDRIVA */
1071 
1072 typedef struct rpmfcApplyTbl_s {
1073  int (*func) (rpmfc fc);
1075 } * rpmfcApplyTbl;
1076 
1080 /*@-nullassign@*/
1081 /*@unchecked@*/
1083  { rpmfcELF, RPMFC_ELF },
1085 #if defined(RPM_VENDOR_MANDRIVA)
1086  { rpmfcSYMLINK, RPMFC_SYMLINK },
1087 #endif
1088  { NULL, 0 }
1089 };
1090 /*@=nullassign@*/
1091 
1093 {
1094  rpmfcApplyTbl fcat;
1095  const char * s;
1096  char * se;
1097  rpmds ds;
1098  const char * fn;
1099  const char * N;
1100  const char * EVR;
1101  evrFlags Flags;
1102  unsigned char deptype;
1103  int nddict;
1104  int previx;
1105  unsigned int val;
1106  int dix;
1107  int ix;
1108  int i;
1109  int xx;
1110  int skipping;
1111 
1112  miRE mire;
1113  int skipProv = fc->skipProv;
1114  int skipReq = fc->skipReq;
1115  int j;
1116 
1117  if (_filter_execs) {
1118  fc->PFnmire = 0;
1119  fc->PFmires = rpmfcExpandRegexps("%{?__noautoprovfiles}", &fc->PFnmire);
1120  if (fc->PFnmire > 0)
1121  rpmlog(RPMLOG_DEBUG, D_("added %d %%__noautoprovfiles patterns.\n"),
1122  fc->PFnmire);
1123  fc->RFnmire = 0;
1124  fc->RFmires = rpmfcExpandRegexps("%{?__noautoreqfiles}", &fc->RFnmire);
1125  if (fc->RFnmire > 0)
1126  rpmlog(RPMLOG_DEBUG, D_("added %d %%__noautoreqfiles patterns.\n"),
1127  fc->RFnmire);
1128  fc->Pnmire = 0;
1129  fc->Pmires = rpmfcExpandRegexps("%{?__noautoprov}", &fc->Pnmire);
1130  if (fc->Pnmire > 0)
1131  rpmlog(RPMLOG_DEBUG, D_("added %d %%__noautoprov patterns.\n"),
1132  fc->Pnmire);
1133  fc->Rnmire = 0;
1134  fc->Rmires = rpmfcExpandRegexps("%{?__noautoreq}", &fc->Rnmire);
1135  if (fc->Rnmire > 0)
1136  rpmlog(RPMLOG_DEBUG, D_("added %d %%__noautoreq patterns.\n"),
1137  fc->Rnmire);
1138  }
1139 
1140 /* Make sure something didn't go wrong previously! */
1141 assert(fc->fn != NULL);
1142  /* Generate package and per-file dependencies. */
1143  for (fc->ix = 0; fc->fn[fc->ix] != NULL; fc->ix++) {
1144 
1145  /* XXX Insure that /usr/{share,lib{,64}}/python files are marked RPMFC_PYTHON */
1146  /* XXX HACK: classification by path is intrinsically stupid. */
1147  { fn = strstr(fc->fn[fc->ix], "/usr/lib");
1148  if (fn) {
1149  fn += sizeof("/usr/lib")-1;
1150  if ((fn[0] == '3' && fn[1] == '2') ||
1151  (fn[0] == '6' && fn[1] == '4'))
1152  fn += 2;
1153  if (!strncmp(fn, "/python", sizeof("/python")-1))
1154  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
1155  else if (!strncmp(fn, "/ruby", sizeof("/ruby")-1)) {
1156  fc->fcolor->vals[fc->ix] |= RPMFC_RUBY;
1157  if ((strstr(fn, ".gemspec") || strstr(fn, "rbconfig.rb"))) {
1159  if (!mireRegcomp(mire, ".*/(specifications/.*\\.gemspec|rbconfig\\.rb)$"))
1160  if (mireRegexec(mire, fc->fn[fc->ix], (size_t) 0) >= 0)
1161  fc->fcolor->vals[fc->ix] |= RPMFC_MODULE;
1162  mire = mireFree(mire);
1163  }
1164  }
1165  /* XXX: lacking better, more generic classifier... */
1166  else if (!strncmp(fn, "/gstreamer", sizeof("/gstreamer")-1) &&
1167  fc->fcolor->vals[fc->ix] & RPMFC_LIBRARY)
1168  fc->fcolor->vals[fc->ix] |= (RPMFC_MODULE|RPMFC_SCRIPT);
1169 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_PLD)
1170  } else {
1172  if (!mireRegcomp(mire, "^.*((/lib/modules/|/var/lib/dkms/).*\\.ko(\\.gz|\\.xz)?|(/var/lib/dkms-binary/[^/]+/[^/]+|/usr/src)/[^/]+/dkms.conf)$"))
1173  if (mireRegexec(mire, fc->fn[fc->ix], (size_t) 0) >= 0)
1174  fc->fcolor->vals[fc->ix] |= (RPMFC_MODULE|RPMFC_SCRIPT);
1175  mire = mireFree(mire);
1176 #endif
1177  }
1178  fn = strstr(fc->fn[fc->ix], "/usr/share");
1179  if (fn) {
1180  fn += sizeof("/usr/share")-1;
1181  if (!strncmp(fn, "/python", sizeof("/python")-1))
1182  fc->fcolor->vals[fc->ix] |= RPMFC_PYTHON;
1183  else if (!strncmp(fn, "/ruby", sizeof("/ruby")-1)) {
1184  fc->fcolor->vals[fc->ix] |= RPMFC_RUBY;
1185  if ((strstr(fn, ".gemspec") || strstr(fn, "rbconfig.rb"))) {
1187  if (!mireRegcomp(mire, ".*/(specifications/.*\\.gemspec|rbconfig\\.rb)$"))
1188  if (mireRegexec(mire, fc->fn[fc->ix], (size_t) 0) >= 0)
1189  fc->fcolor->vals[fc->ix] |= RPMFC_MODULE;
1190  mire = mireFree(mire);
1191  }
1192  }
1193  }
1194  }
1195 
1196  /* XXX ugly quick & dirty integration of haskell() dependencies */
1197  { fn = strstr(fc->fn[fc->ix], "/usr/share/haskell-deps");
1198  if (fn)
1199  fc->fcolor->vals[fc->ix] |= RPMFC_HASKELL;
1200  }
1201 
1202  if (fc->fcolor->vals[fc->ix])
1203  for (fcat = rpmfcApplyTable; fcat->func != NULL; fcat++) {
1204  if (!(fc->fcolor->vals[fc->ix] & fcat->colormask))
1205  /*@innercontinue@*/ continue;
1206 
1207  if (_filter_execs) {
1208  fc->skipProv = skipProv;
1209  fc->skipReq = skipReq;
1210  if ((mire = (miRE)fc->PFmires) != NULL)
1211  for (j = 0; j < fc->PFnmire; j++, mire++) {
1212  fn = fc->fn[fc->ix] + fc->brlen;
1213  if ((xx = mireRegexec(mire, fn, 0)) < 0)
1214  /*@innercontinue@*/ continue;
1215  rpmlog(RPMLOG_NOTICE, _("skipping %s provides detection\n"),
1216  fn);
1217  fc->skipProv = 1;
1218  /*@innerbreak@*/ break;
1219  }
1220  if ((mire = (miRE)fc->RFmires) != NULL)
1221  for (j = 0; j < fc->RFnmire; j++, mire++) {
1222  fn = fc->fn[fc->ix] + fc->brlen;
1223  if ((xx = mireRegexec(mire, fn, 0)) < 0)
1224  /*@innercontinue@*/ continue;
1225  rpmlog(RPMLOG_NOTICE, _("skipping %s requires detection\n"),
1226  fn);
1227  fc->skipReq = 1;
1228  /*@innerbreak@*/ break;
1229  }
1230  }
1231 
1232  struct stat sb, * st = &sb;
1233  if (stat(fc->fn[fc->ix], st) == 0 && !(st->st_mode & (S_IFBLK|S_IFCHR)))
1234  xx = (*fcat->func) (fc);
1235  }
1236  }
1237 
1238  if (_filter_execs) {
1239  fc->PFmires = rpmfcFreeRegexps(fc->PFmires, fc->PFnmire);
1240  fc->RFmires = rpmfcFreeRegexps(fc->RFmires, fc->RFnmire);
1241  fc->Pmires = rpmfcFreeRegexps(fc->Pmires, fc->Pnmire);
1242  fc->Rmires = rpmfcFreeRegexps(fc->Rmires, fc->Rnmire);
1243  }
1244  fc->skipProv = skipProv;
1245  fc->skipReq = skipReq;
1246 
1247  /* Generate per-file indices into package dependencies. */
1248  nddict = argvCount(fc->ddict);
1249  previx = -1;
1250  for (i = 0; i < nddict; i++) {
1251  s = fc->ddict[i];
1252 
1253  /* Parse out (file#,deptype,N,EVR,Flags) */
1254  ix = strtol(s, &se, 10);
1255 assert(se != NULL);
1256  deptype = *se++;
1257  se++;
1258  N = se;
1259  while (*se && *se != ' ')
1260  se++;
1261  *se++ = '\0';
1262  EVR = se;
1263  while (*se && *se != ' ')
1264  se++;
1265  *se++ = '\0';
1266  Flags = (evrFlags) strtol(se, NULL, 16);
1267 
1268  dix = -1;
1269  skipping = 0;
1270  switch (deptype) {
1271  default:
1272  /*@switchbreak@*/ break;
1273  case 'P':
1274  skipping = fc->skipProv;
1275  ds = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
1276  dix = rpmdsFind(fc->provides, ds);
1277  (void)rpmdsFree(ds);
1278  ds = NULL;
1279  /*@switchbreak@*/ break;
1280  case 'R':
1281  skipping = fc->skipReq;
1282  ds = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags);
1283  dix = rpmdsFind(fc->requires, ds);
1284  (void)rpmdsFree(ds);
1285  ds = NULL;
1286  /*@switchbreak@*/ break;
1287  }
1288 
1289 /* XXX assertion incorrect while generating -debuginfo deps. */
1290 #if 0
1291 assert(dix >= 0);
1292 #else
1293  if (dix < 0)
1294  continue;
1295 #endif
1296 
1297  val = (deptype << 24) | (dix & 0x00ffffff);
1298  xx = argiAdd(&fc->ddictx, -1, val);
1299 
1300  if (previx != ix) {
1301  previx = ix;
1302  xx = argiAdd(&fc->fddictx, ix, argiCount(fc->ddictx)-1);
1303  }
1304  if (fc->fddictn && fc->fddictn->vals && !skipping)
1305  fc->fddictn->vals[ix]++;
1306  }
1307 
1308  return RPMRC_OK;
1309 }
1310 
1312 {
1313  ARGV_t fcav = NULL;
1314  ARGV_t dav;
1315  rpmmg mg = NULL;
1316  const char * s, * se;
1317  size_t slen;
1318  int fcolor;
1319  int xx;
1320  const char * magicfile = NULL;
1321 
1322  if (fc == NULL || argv == NULL)
1323  return RPMRC_OK;
1324 
1325  magicfile = rpmExpand("%{?_rpmfc_magic_path}", NULL);
1326  if (magicfile == NULL || *magicfile == '\0')
1327  magicfile = _free(magicfile);
1328 
1329  mg = rpmmgNew(magicfile, 0);
1330 assert(mg != NULL); /* XXX figger a proper return path. */
1331 
1332  fc->nfiles = argvCount(argv);
1333 
1334  /* Initialize the per-file dictionary indices. */
1335  xx = argiAdd(&fc->fddictx, fc->nfiles-1, 0);
1336  xx = argiAdd(&fc->fddictn, fc->nfiles-1, 0);
1337 
1338  /* Build (sorted) file class dictionary. */
1339  xx = argvAdd(&fc->cdict, "");
1340  xx = argvAdd(&fc->cdict, "directory");
1341 
1342  for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
1343  const char * ftype;
1344  int freeftype;
1345  rpmuint16_t mode = (fmode ? fmode[fc->ix] : 0);
1346  int urltype;
1347 
1348  ftype = ""; freeftype = 0;
1349  urltype = urlPath(argv[fc->ix], &s);
1350 assert(s != NULL && *s == '/');
1351  slen = strlen(s);
1352 
1353  switch (mode & S_IFMT) {
1354  case S_IFCHR: ftype = "character special"; /*@switchbreak@*/ break;
1355  case S_IFBLK: ftype = "block special"; /*@switchbreak@*/ break;
1356 #if defined(S_IFIFO)
1357  case S_IFIFO: ftype = "fifo (named pipe)"; /*@switchbreak@*/ break;
1358 #endif
1359 #if defined(S_IFSOCK)
1360 /*@-unrecog@*/
1361  case S_IFSOCK: ftype = "socket"; /*@switchbreak@*/ break;
1362 /*@=unrecog@*/
1363 #endif
1364  case S_IFDIR:
1365  case S_IFLNK:
1366  case S_IFREG:
1367  default:
1368 
1369 #define _suffix(_s, _x) \
1370  (slen >= sizeof(_x) && !strcmp((_s)+slen-(sizeof(_x)-1), (_x)))
1371 
1372  /* XXX all files with extension ".pm" are perl modules for now. */
1373  if (_suffix(s, ".pm"))
1374  ftype = "Perl5 module source text";
1375 
1376  /* XXX all files with extension ".jar" are java archives for now. */
1377  else if (_suffix(s, ".jar"))
1378  ftype = "Java archive file";
1379 
1380  /* XXX all files with extension ".class" are java class files for now. */
1381  else if (_suffix(s, ".class"))
1382  ftype = "Java class file";
1383 
1384  /* XXX all files with extension ".la" are libtool for now. */
1385  else if (_suffix(s, ".la"))
1386  ftype = "libtool library file";
1387 
1388  /* XXX all files with extension ".pc" are pkgconfig for now. */
1389  else if (_suffix(s, ".pc"))
1390  ftype = "pkgconfig file";
1391 
1392  /* XXX all files with extension ".php" are PHP for now. */
1393  else if (_suffix(s, ".php"))
1394  ftype = "PHP script text";
1395 
1396  else if (_suffix(s, ".desktop"))
1397  ftype = "Desktop Entry";
1398 
1399  /* XXX files with extension ".typelib" are GNOME typelib for now. */
1400  else if (_suffix(s, ".typelib"))
1401  ftype = "G-IR binary database";
1402 
1403  /* XXX files with extension ".js" have GNOME typelib requires for now */
1404  else if (_suffix(s, ".js"))
1405  ftype = "G-IR binary database";
1406 
1407  /* XXX skip all files in /dev/ which are (or should be) %dev dummies. */
1408  else if (slen >= fc->brlen+sizeof("/dev/") && !strncmp(s+fc->brlen, "/dev/", sizeof("/dev/")-1))
1409  ftype = "";
1410  else if (magicfile) {
1411  ftype = rpmmgFile(mg, s);
1412 assert(ftype != NULL); /* XXX never happens, rpmmgFile() returns "" */
1413  freeftype = 1;
1414  }
1415  /*@switchbreak@*/ break;
1416  }
1417 
1418  se = ftype;
1419 
1420 if (_rpmfc_debug) /* XXX noisy */
1421  rpmlog(RPMLOG_DEBUG, "%s: %s\n", s, se);
1422 
1423  /* Save the path. */
1424  xx = argvAdd(&fc->fn, s);
1425 
1426  /* Save the file type string. */
1427  xx = argvAdd(&fcav, se);
1428 
1429  /* Add (filtered) entry to sorted class dictionary. */
1430  fcolor = rpmfcColoring(se);
1431  xx = argiAdd(&fc->fcolor, (int)fc->ix, fcolor);
1432 
1433  if (fcolor != RPMFC_WHITE && (fcolor & RPMFC_INCLUDE))
1434  xx = rpmfcSaveArg(&fc->cdict, se);
1435 
1436 /*@-modobserver -observertrans @*/ /* XXX mixed types in variable */
1437  if (freeftype)
1438  ftype = _free(ftype);
1439 /*@=modobserver =observertrans @*/
1440  }
1441 
1442  /* Build per-file class index array. */
1443  fc->fknown = 0;
1444  for (fc->ix = 0; fc->ix < fc->nfiles; fc->ix++) {
1445  se = fcav[fc->ix];
1446 assert(se != NULL);
1447 
1448  dav = argvSearch(fc->cdict, se, NULL);
1449  if (dav) {
1450  xx = argiAdd(&fc->fcdictx, (int)fc->ix, (dav - fc->cdict));
1451  fc->fknown++;
1452  } else {
1453  xx = argiAdd(&fc->fcdictx, (int)fc->ix, 0);
1454  fc->fwhite++;
1455  }
1456  }
1457 
1458  fcav = argvFree(fcav);
1459 
1460  mg = rpmmgFree(mg);
1462  D_("categorized %d files into %u classes (using %s).\n"),
1463  (unsigned)fc->nfiles, argvCount(fc->cdict), magicfile);
1464  magicfile = _free(magicfile);
1465 
1466  return RPMRC_OK;
1467 }
1468 
1471 typedef struct DepMsg_s * DepMsg_t;
1472 
1475 struct DepMsg_s {
1476 /*@observer@*/ /*@null@*/
1477  const char * msg;
1478 /*@observer@*/
1479  const char * argv[4];
1483  int mask;
1484  int toggle;
1485 };
1486 
1489 /*@-nullassign@*/
1490 /*@unchecked@*/
1491 static struct DepMsg_s depMsgs[] = {
1492  { "Provides", { "%{?__find_provides}", NULL, NULL, NULL },
1494  0, -1 },
1495  { "Requires(interp)", { NULL, "interp", NULL, NULL },
1497  _notpre(RPMSENSE_INTERP), 0 },
1498  { "Requires(rpmlib)", { NULL, "rpmlib", NULL, NULL },
1499  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1500  _notpre(RPMSENSE_RPMLIB), 0 },
1501  { "Requires(verify)", { NULL, "verify", NULL, NULL },
1502  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1503  RPMSENSE_SCRIPT_VERIFY, 0 },
1504  { "Requires(pre)", { NULL, "pre", NULL, NULL },
1505  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1506  _notpre(RPMSENSE_SCRIPT_PRE), 0 },
1507  { "Requires(post)", { NULL, "post", NULL, NULL },
1508  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1509  _notpre(RPMSENSE_SCRIPT_POST), 0 },
1510  { "Requires(preun)", { NULL, "preun", NULL, NULL },
1511  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1512  _notpre(RPMSENSE_SCRIPT_PREUN), 0 },
1513  { "Requires(postun)", { NULL, "postun", NULL, NULL },
1514  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS,
1515  _notpre(RPMSENSE_SCRIPT_POSTUN), 0 },
1516  { "Requires", { "%{?__find_requires}", NULL, NULL, NULL },
1517  (rpmTag)-1, (rpmTag)-1, RPMTAG_REQUIREFLAGS, /* XXX inherit name/version arrays */
1518  RPMSENSE_FIND_REQUIRES|RPMSENSE_TRIGGERIN|RPMSENSE_TRIGGERUN|RPMSENSE_TRIGGERPOSTUN|RPMSENSE_TRIGGERPREIN, 0 },
1519  { "Conflicts", { "%{?__find_conflicts}", NULL, NULL, NULL },
1521  0, -1 },
1522  { "Obsoletes", { "%{?__find_obsoletes}", NULL, NULL, NULL },
1524  0, -1 },
1525  { NULL, { NULL, NULL, NULL, NULL }, (rpmTag)0, (rpmTag)0, (rpmTag)0, 0, 0 }
1526 };
1527 /*@=nullassign@*/
1528 
1529 /*@unchecked@*/
1530 static DepMsg_t DepMsgs = depMsgs;
1531 
1536 static void printDeps(Header h)
1537  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1538  /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
1539 {
1540  DepMsg_t dm;
1541  rpmds ds = NULL;
1542  int flags = 0x2; /* XXX no filtering, !scareMem */
1543  const char * DNEVR;
1544  evrFlags Flags;
1545  int bingo = 0;
1546 
1547  for (dm = DepMsgs; dm->msg != NULL; dm++) {
1548  if ((int)dm->ntag != -1) {
1549  (void)rpmdsFree(ds);
1550  ds = NULL;
1551  ds = rpmdsNew(h, dm->ntag, flags);
1552  }
1553  if (dm->ftag == 0)
1554  continue;
1555 
1556  ds = rpmdsInit(ds);
1557  if (ds == NULL)
1558  continue; /* XXX can't happen */
1559 
1560  bingo = 0;
1561  while (rpmdsNext(ds) >= 0) {
1562 
1563  Flags = rpmdsFlags(ds);
1564 
1565  if (!((Flags & dm->mask) ^ (dm->toggle)))
1566  /*@innercontinue@*/ continue;
1567  if (bingo == 0) {
1568  rpmlog(RPMLOG_NOTICE, "%s:", (dm->msg ? dm->msg : ""));
1569  bingo = 1;
1570  }
1571  if ((DNEVR = rpmdsDNEVR(ds)) == NULL)
1572  /*@innercontinue@*/ continue; /* XXX can't happen */
1573  rpmlog(RPMLOG_NOTICE, " %s", DNEVR+2);
1574  }
1575  if (bingo)
1576  rpmlog(RPMLOG_NOTICE, "\n");
1577  }
1578  (void)rpmdsFree(ds);
1579  ds = NULL;
1580 }
1581 
1585  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1586  /*@modifies fi, rpmGlobalMacroContext, fileSystem, internalState @*/
1587 {
1588  rpmiob iob_stdin;
1589  rpmiob iob_stdout;
1590  DepMsg_t dm;
1591  int failnonzero = 0;
1592  rpmRC rc = RPMRC_OK;
1593 
1594  /*
1595  * Create file manifest buffer to deliver to dependency finder.
1596  */
1597  iob_stdin = rpmiobNew(0);
1598  fi = rpmfiInit(fi, 0);
1599  if (fi != NULL)
1600  while (rpmfiNext(fi) >= 0)
1601  iob_stdin = rpmiobAppend(iob_stdin, rpmfiFN(fi), 1);
1602 
1603  for (dm = DepMsgs; dm->msg != NULL; dm++) {
1604  rpmTag tag;
1605  rpmsenseFlags tagflags;
1606  char * s;
1607  int xx;
1608 
1609  tag = (dm->ftag > 0) ? dm->ftag : dm->ntag;
1610  tagflags = (rpmsenseFlags) 0;
1611  s = NULL;
1612 
1613  switch(tag) {
1614  case RPMTAG_PROVIDEFLAGS:
1615  if (!pkg->autoProv)
1616  continue;
1617  failnonzero = 1;
1618  tagflags = RPMSENSE_FIND_PROVIDES;
1619  /*@switchbreak@*/ break;
1620  case RPMTAG_REQUIREFLAGS:
1621  if (!pkg->autoReq)
1622  continue;
1623  failnonzero = 0;
1624  tagflags = RPMSENSE_FIND_REQUIRES;
1625  /*@switchbreak@*/ break;
1626  default:
1627  continue;
1628  /*@notreached@*/ /*@switchbreak@*/ break;
1629  }
1630 
1631  xx = rpmfcExec(dm->argv, iob_stdin, &iob_stdout, failnonzero);
1632  if (xx == -1)
1633  continue;
1634 
1635  s = rpmExpand(dm->argv[0], NULL);
1636  rpmlog(RPMLOG_NOTICE, _("Finding %s: %s\n"), dm->msg,
1637  (s ? s : ""));
1638  s = _free(s);
1639 
1640  if (iob_stdout == NULL) {
1641  rpmlog(RPMLOG_ERR, _("Failed to find %s:\n"), dm->msg);
1642  rc = RPMRC_FAIL;
1643  break;
1644  }
1645 
1646  /* Parse dependencies into header */
1647  if (spec->_parseRCPOT)
1648  rc = spec->_parseRCPOT(spec, pkg, rpmiobStr(iob_stdout), tag,
1649  0, tagflags);
1650  iob_stdout = rpmiobFree(iob_stdout);
1651 
1652  if (rc) {
1653  rpmlog(RPMLOG_ERR, _("Failed to find %s:\n"), dm->msg);
1654  break;
1655  }
1656  }
1657 
1658  iob_stdin = rpmiobFree(iob_stdin);
1659 
1660  return rc;
1661 }
1662 
1665 /*@-nullassign@*/
1666 /*@unchecked@*/
1667 static struct DepMsg_s scriptMsgs[] = {
1668  { "Requires(pre)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
1670  RPMSENSE_SCRIPT_PRE, 0 },
1671  { "Requires(post)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
1673  RPMSENSE_SCRIPT_POST, 0 },
1674  { "Requires(preun)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
1676  RPMSENSE_SCRIPT_PREUN, 0 },
1677  { "Requires(postun)", { "%{?__scriptlet_requires}", NULL, NULL, NULL },
1679  RPMSENSE_SCRIPT_POSTUN, 0 },
1680  { NULL, { NULL, NULL, NULL, NULL }, (rpmTag)0, (rpmTag)0, (rpmTag)0, 0, 0 }
1681 };
1682 /*@=nullassign@*/
1683 
1684 /*@unchecked@*/
1685 static DepMsg_t ScriptMsgs = scriptMsgs;
1686 
1690  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1691  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
1692 {
1693  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1694  rpmiob iob_stdin = rpmiobNew(0);
1695  rpmiob iob_stdout = NULL;
1696  DepMsg_t dm;
1697  int failnonzero = 0;
1698  int rc = 0;
1699  int xx;
1700 
1701  for (dm = ScriptMsgs; dm->msg != NULL; dm++) {
1702  rpmTag tag;
1703  rpmsenseFlags tagflags;
1704  char * s;
1705 
1706  tag = dm->ftag;
1707  tagflags = (rpmsenseFlags) (RPMSENSE_FIND_REQUIRES | dm->mask);
1708 
1709  /* Retrieve scriptlet interpreter. */
1710  he->tag = dm->ntag;
1711  xx = headerGet(pkg->header, he, 0);
1712  if (!xx || he->p.str == NULL)
1713  continue;
1714  xx = strcmp(he->p.str, "/bin/sh") && strcmp(he->p.str, "/bin/bash");
1715  he->p.ptr = _free(he->p.ptr);
1716  if (xx)
1717  continue;
1718 
1719  /* Retrieve scriptlet body. */
1720  he->tag = dm->vtag;
1721  xx = headerGet(pkg->header, he, 0);
1722  if (!xx || he->p.str == NULL)
1723  continue;
1724  iob_stdin = rpmiobEmpty(iob_stdin);
1725  iob_stdin = rpmiobAppend(iob_stdin, he->p.str, 1);
1726  iob_stdin = rpmiobRTrim(iob_stdin);
1727  he->p.ptr = _free(he->p.ptr);
1728 
1729  xx = rpmfcExec(dm->argv, iob_stdin, &iob_stdout, failnonzero);
1730  if (xx == -1)
1731  continue;
1732 
1733  /* Parse dependencies into header */
1734  s = rpmiobStr(iob_stdout);
1735  if (s != NULL && *s != '\0') {
1736  char * se = s;
1737  /* XXX Convert "executable(/path/to/file)" to "/path/to/file". */
1738  while ((se = strstr(se, "executable(/")) != NULL) {
1739 /*@-modobserver@*/ /* FIX: rpmiobStr should not be observer */
1740  se = stpcpy(se, " ");
1741  *se = '/'; /* XXX stpcpy truncates the '/' */
1742 /*@=modobserver@*/
1743  se = strchr(se, ')');
1744  if (se == NULL)
1745  /*@innerbreak@*/ break;
1746  *se++ = ' ';
1747  }
1748  if (spec->_parseRCPOT)
1749  rc = spec->_parseRCPOT(spec, pkg, s, tag, 0, tagflags);
1750  }
1751  iob_stdout = rpmiobFree(iob_stdout);
1752 
1753  }
1754 
1755  iob_stdin = rpmiobFree(iob_stdin);
1756 
1757  return rc;
1758 }
1759 
1760 static unsigned removeSillyDeps(Header h, rpmfc fc) {
1761  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1762  int xx;
1763  unsigned i, rnum, removed = 0;
1764  const char **deps = NULL;
1765  const char **versions = NULL;
1766  evrFlags *flags = NULL;
1767  int *newpos = NULL, *ddictxPos = NULL;
1768 
1769  he->tag = RPMTAG_REQUIRENAME;
1770  xx = headerGet(h, he, 0);
1771  deps = he->p.argv;
1772  rnum = he->c;
1773 
1774  he->tag = RPMTAG_REQUIREVERSION;
1775  xx = headerGet(h, he, 0);
1776  versions = he->p.argv;
1777 
1778  he->tag = RPMTAG_REQUIREFLAGS;
1779  xx = headerGet(h, he, 0);
1780  flags = (evrFlags*)he->p.ui32p;
1781 
1782  if (fc && fc->requires != NULL && fc->ddictx != NULL) {
1783  newpos = alloca(he->c*sizeof(newpos[0]));
1784  if (fc->ddictx)
1785  ddictxPos = alloca(fc->ddictx->nvals*sizeof(ddictxPos[0]));
1786  }
1787  for (i = 0; i < rnum-removed; i++) {
1788  if (removed) {
1789  deps[i] = deps[i+removed];
1790  versions[i] = versions[i+removed];
1791  flags[i] = flags[i+removed];
1792  if (fc) {
1793  fc->requires->N[i] = fc->requires->N[i+removed];
1794  fc->requires->EVR[i] = fc->requires->EVR[i+removed];
1795  fc->requires->Flags[i] = fc->requires->Flags[i+removed];
1796  }
1797  }
1798  if (fc && fc->requires != NULL && fc->ddictx != NULL)
1799  newpos[i+removed] = i;
1800  rpmds req = rpmdsSingle(RPMTAG_REQUIRENAME, deps[i], versions[i], flags[i]);
1801  rpmds prov = rpmdsNew(h, (*deps[i] == '/' && !*versions[i]) ? RPMTAG_BASENAMES : RPMTAG_PROVIDENAME, 0);
1802  if (rpmdsMatch(req, prov)) {
1803  if (flags[i] & RPMSENSE_SCRIPT_PRE)
1804  rpmlog(RPMLOG_ERR, "Requires(pre): on dependency provided by self: %s\n", rpmdsDNEVR(req));
1805  else {
1806  if (fc && fc->requires != NULL && fc->ddictx != NULL)
1807  newpos[i+removed] = -1;
1808  rpmlog(RPMLOG_NOTICE, "Removing dependency on self: %s\n", rpmdsDNEVR(req));
1809  removed++;
1810  i--;
1811  }
1812  }
1813  req = rpmdsFree(req);
1814  prov = rpmdsFree(prov);
1815  }
1816  if (fc && fc->requires != NULL && fc->ddictx != NULL && removed) {
1817  fc->requires->Count -= removed;
1818  unsigned rx = 0;
1819  for (i = 0; i < fc->ddictx->nvals-rx; i++) {
1820  unsigned ix;
1821  unsigned char deptype;
1822 
1823  ix = fc->ddictx->vals[i+rx];
1824  deptype = ((ix >> 24) & 0xff);
1825  ix &= 0x00ffffff;
1826 
1827  if (deptype == 'P') {
1828  ddictxPos[i+rx] = i;
1829  fc->ddictx->vals[i] = fc->ddictx->vals[i+rx];
1830  continue;
1831  }
1832  if (newpos[ix] == -1) {
1833  ddictxPos[i+rx] = -1;
1834  i--, rx++;
1835  }
1836  else
1837  {
1838  ddictxPos[i+rx] = i;
1839  fc->ddictx->vals[i] = (deptype << 24) | (newpos[ix] & 0x00ffffff);
1840  }
1841  }
1842  fc->ddictx->nvals -= rx;
1843 
1844  for (i = 0; i < fc->fddictn->nvals; i++) {
1845  rx = 0;
1846  if (fc->fddictn->vals[i]) {
1847  unsigned j, ix = fc->fddictx->vals[i];
1848  for (j = 0, rx = 0; j < fc->fddictn->vals[i]; j++, ix++) {
1849  if (ddictxPos[ix] == -1)
1850  rx++;
1851  if (j == 0 || fc->fddictx->vals[i] == -1)
1852  fc->fddictx->vals[i] = ddictxPos[ix];
1853  }
1854  }
1855  if (rx)
1856  fc->fddictn->vals[i] -= rx;
1857  if (fc->fddictn->vals[i] == 0)
1858  fc->fddictx->vals[i] = 0;
1859  }
1860  }
1861 
1862  if (removed) {
1863  he->tag = RPMTAG_REQUIRENAME;
1864  he->t = RPM_STRING_ARRAY_TYPE;
1865  he->p.argv = deps;
1866  he->c -= removed;
1867  headerMod(h, he, 0);
1868 
1869  he->tag = RPMTAG_REQUIREVERSION;
1870  he->p.argv = versions;
1871  headerMod(h, he, 0);
1872 
1873  he->tag = RPMTAG_REQUIREFLAGS;
1874  he->t = RPM_UINT32_TYPE;
1875  he->p.ui32p = (uint32_t*)flags;
1876  headerMod(h, he, 0);
1877  }
1878 
1879  return removed;
1880 }
1881 
1882 rpmRC rpmfcGenerateDepends(void * _spec, void * _pkg)
1883 {
1884  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1885  const Spec spec = (Spec) _spec;
1886  Package pkg = (Package) _pkg;
1887  rpmfi fi = pkg->fi;
1888  rpmfc fc = NULL;
1889  rpmds ds;
1890  int flags = 0x2; /* XXX no filtering, !scareMem */
1891  ARGV_t av;
1892  rpmuint16_t * fmode;
1893  int ac = rpmfiFC(fi);
1894  char buf[BUFSIZ];
1895  const char * N;
1896  const char * EVR;
1897  int genConfigDeps, internaldeps;
1898  rpmRC rc = RPMRC_OK;
1899  int i;
1900  int xx;
1901 
1902  /* Skip packages with no files. */
1903  if (ac <= 0)
1904  return RPMRC_OK;
1905 
1906  /* Skip packages that have dependency generation disabled. */
1907  if (! (pkg->autoReq || pkg->autoProv))
1908  return RPMRC_OK;
1909 
1910  /* If new-fangled dependency generation is disabled ... */
1911  internaldeps = rpmExpandNumeric("%{?_use_internal_dependency_generator}");
1912  if (internaldeps == 0) {
1913  /* ... then generate dependencies using %{__find_requires} et al. */
1914  rc = rpmfcGenerateDependsHelper(spec, pkg, fi);
1915  removeSillyDeps(pkg->header, NULL);
1916  printDeps(pkg->header);
1917  return rc;
1918  }
1919 
1920  /* Generate scriptlet Dependencies. */
1921  if (internaldeps > 1)
1922  xx = rpmfcGenerateScriptletDeps(spec, pkg);
1923 
1924  /* Extract absolute file paths in argv format. */
1925  /* XXX TODO: should use argvFoo ... */
1926  av = (ARGV_t) xcalloc(ac+1, sizeof(*av));
1927  fmode = (rpmuint16_t *) xcalloc(ac+1, sizeof(*fmode));
1928 
1929  genConfigDeps = 0;
1930  fi = rpmfiInit(fi, 0);
1931  if (fi != NULL)
1932  while ((i = rpmfiNext(fi)) >= 0) {
1933  rpmfileAttrs fileAttrs;
1934 
1935  /* Does package have any %config files? */
1936  fileAttrs = (rpmfileAttrs) rpmfiFFlags(fi);
1937  genConfigDeps |= (fileAttrs & RPMFILE_CONFIG);
1938 
1939  av[i] = xstrdup(rpmfiFN(fi));
1940  fmode[i] = rpmfiFMode(fi);
1941  }
1942  av[ac] = NULL;
1943 
1944  fc = rpmfcNew();
1945  fc->skipProv = !pkg->autoProv;
1946  fc->skipReq = !pkg->autoReq;
1947  fc->tracked = 0;
1948 
1949  { const char * buildRootURL;
1950  const char * buildRoot;
1951  buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
1952  (void) urlPath(buildRootURL, &buildRoot);
1953  if (buildRoot && !strcmp(buildRoot, "/")) buildRoot = NULL;
1954  fc->brlen = (buildRoot ? strlen(buildRoot) : 0);
1955  buildRootURL = _free(buildRootURL);
1956  }
1957 
1958  /* Copy (and delete) manually generated dependencies to dictionary. */
1959  if (!fc->skipProv) {
1960  ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, flags);
1961  xx = rpmdsMerge(&fc->provides, ds);
1962  (void)rpmdsFree(ds);
1963  ds = NULL;
1964  he->tag = RPMTAG_PROVIDENAME;
1965  xx = headerDel(pkg->header, he, 0);
1966  he->tag = RPMTAG_PROVIDEVERSION;
1967  xx = headerDel(pkg->header, he, 0);
1968  he->tag = RPMTAG_PROVIDEFLAGS;
1969  xx = headerDel(pkg->header, he, 0);
1970 
1971  /* Add config dependency, Provides: config(N) = EVR */
1972  if (genConfigDeps) {
1973  static evrFlags _Flags = (evrFlags)(RPMSENSE_EQUAL|RPMSENSE_CONFIG);
1974  N = rpmdsN(pkg->ds);
1975 assert(N != NULL);
1976  EVR = rpmdsEVR(pkg->ds);
1977 assert(EVR != NULL);
1978  sprintf(buf, "config(%s)", N);
1979  ds = rpmdsSingle(RPMTAG_PROVIDENAME, buf, EVR, _Flags);
1980  xx = rpmdsMerge(&fc->provides, ds);
1981  (void)rpmdsFree(ds);
1982  ds = NULL;
1983  }
1984  }
1985 
1986  if (!fc->skipReq) {
1987  ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, flags);
1988  xx = rpmdsMerge(&fc->requires, ds);
1989  (void)rpmdsFree(ds);
1990  ds = NULL;
1991  he->tag = RPMTAG_REQUIRENAME;
1992  xx = headerDel(pkg->header, he, 0);
1993  he->tag = RPMTAG_REQUIREVERSION;
1994  xx = headerDel(pkg->header, he, 0);
1995  he->tag = RPMTAG_REQUIREFLAGS;
1996  xx = headerDel(pkg->header, he, 0);
1997 
1998  /* Add config dependency, Requires: config(N) = EVR */
1999  if (genConfigDeps) {
2000  static evrFlags _Flags = (evrFlags)(RPMSENSE_EQUAL|RPMSENSE_CONFIG);
2001  N = rpmdsN(pkg->ds);
2002 assert(N != NULL);
2003  EVR = rpmdsEVR(pkg->ds);
2004 assert(EVR != NULL);
2005  sprintf(buf, "config(%s)", N);
2006  ds = rpmdsSingle(RPMTAG_REQUIRENAME, buf, EVR, _Flags);
2007  xx = rpmdsMerge(&fc->requires, ds);
2008  (void)rpmdsFree(ds);
2009  ds = NULL;
2010  }
2011  }
2012 
2013  /* Build file class dictionary. */
2014  xx = rpmfcClassify(fc, av, fmode);
2015 
2016  /* Build file/package dependency dictionary. */
2017  xx = rpmfcApply(fc);
2018 
2019  /* Add per-file colors(#files) */
2020  he->tag = RPMTAG_FILECOLORS;
2021  he->t = RPM_UINT32_TYPE;
2022  he->p.ui32p = argiData(fc->fcolor);
2023  he->c = argiCount(fc->fcolor);
2024 assert(ac == (int)he->c);
2025  if (he->p.ptr != NULL && he->c > 0) {
2026  rpmuint32_t * fcolors = he->p.ui32p;
2027 
2028  /* XXX Make sure only primary (i.e. Elf32/Elf64) colors are added. */
2029  for (i = 0; i < (int)he->c; i++)
2030  fcolors[i] &= 0x0f;
2031 
2032  xx = headerPut(pkg->header, he, 0);
2033  }
2034 
2035  /* Add classes(#classes) */
2036  he->tag = RPMTAG_CLASSDICT;
2037  he->t = RPM_STRING_ARRAY_TYPE;
2038  he->p.argv = argvData(fc->cdict);
2039  he->c = argvCount(fc->cdict);
2040  if (he->p.ptr != NULL && he->c > 0) {
2041  xx = headerPut(pkg->header, he, 0);
2042  }
2043 
2044  /* Add per-file classes(#files) */
2045  he->tag = RPMTAG_FILECLASS;
2046  he->t = RPM_UINT32_TYPE;
2047  he->p.ui32p = argiData(fc->fcdictx);
2048  he->c = argiCount(fc->fcdictx);
2049 assert(ac == (int)he->c);
2050  if (he->p.ptr != NULL && he->c > 0) {
2051  xx = headerPut(pkg->header, he, 0);
2052  }
2053 
2054  /* Add Provides: */
2055  if (fc->provides != NULL && (he->c = rpmdsCount(fc->provides)) > 0
2056  && !fc->skipProv)
2057  {
2058  he->tag = RPMTAG_PROVIDENAME;
2059  he->t = RPM_STRING_ARRAY_TYPE;
2060  he->p.argv = fc->provides->N;
2061  xx = headerPut(pkg->header, he, 0);
2062 
2063  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
2064 /*@-nullpass@*/
2065  he->tag = RPMTAG_PROVIDEVERSION;
2066  he->t = RPM_STRING_ARRAY_TYPE;
2067  he->p.argv = fc->provides->EVR;
2068 assert(he->p.ptr != NULL);
2069  xx = headerPut(pkg->header, he, 0);
2070 
2071  he->tag = RPMTAG_PROVIDEFLAGS;
2072  he->t = RPM_UINT32_TYPE;
2073  he->p.ui32p = (rpmuint32_t *) fc->provides->Flags;
2074 assert(he->p.ptr != NULL);
2075  xx = headerPut(pkg->header, he, 0);
2076 /*@=nullpass@*/
2077  }
2078 
2079  /* Add Requires: */
2080  if (fc->requires != NULL && (he->c = rpmdsCount(fc->requires)) > 0
2081  && !fc->skipReq)
2082  {
2083  he->tag = RPMTAG_REQUIRENAME;
2084  he->t = RPM_STRING_ARRAY_TYPE;
2085  he->p.argv = fc->requires->N;
2086 assert(he->p.ptr != NULL);
2087  xx = headerPut(pkg->header, he, 0);
2088 
2089  /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */
2090 /*@-nullpass@*/
2091  he->tag = RPMTAG_REQUIREVERSION;
2092  he->t = RPM_STRING_ARRAY_TYPE;
2093  he->p.argv = fc->requires->EVR;
2094 assert(he->p.ptr != NULL);
2095  xx = headerPut(pkg->header, he, 0);
2096 
2097  he->tag = RPMTAG_REQUIREFLAGS;
2098  he->t = RPM_UINT32_TYPE;
2099  he->p.ui32p = (rpmuint32_t *) fc->requires->Flags;
2100 assert(he->p.ptr != NULL);
2101  xx = headerPut(pkg->header, he, 0);
2102 /*@=nullpass@*/
2103  }
2104 
2105  removeSillyDeps(pkg->header, fc);
2106 
2107  /* Add dependency dictionary(#dependencies) */
2108  he->tag = RPMTAG_DEPENDSDICT;
2109  he->t = RPM_UINT32_TYPE;
2110  he->p.ui32p = argiData(fc->ddictx);
2111  he->c = argiCount(fc->ddictx);
2112  if (he->p.ptr != NULL) {
2113  xx = headerPut(pkg->header, he, 0);
2114  }
2115 
2116  /* Add per-file dependency (start,number) pairs (#files) */
2117  he->tag = RPMTAG_FILEDEPENDSX;
2118  he->t = RPM_UINT32_TYPE;
2119  he->p.ui32p = argiData(fc->fddictx);
2120  he->c = argiCount(fc->fddictx);
2121 assert(ac == (int)he->c);
2122  if (he->p.ptr != NULL) {
2123  xx = headerPut(pkg->header, he, 0);
2124  }
2125 
2126  he->tag = RPMTAG_FILEDEPENDSN;
2127  he->t = RPM_UINT32_TYPE;
2128  he->p.ui32p = argiData(fc->fddictn);
2129  he->c = argiCount(fc->fddictn);
2130 assert(ac == (int)he->c);
2131  if (he->p.ptr != NULL) {
2132  xx = headerPut(pkg->header, he, 0);
2133  }
2134 
2135  printDeps(pkg->header);
2136 
2137 if (fc != NULL && _rpmfc_debug) {
2138 char msg[BUFSIZ];
2139 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));
2140 rpmfcPrint(msg, fc, NULL);
2141 }
2142 
2143  /* Clean up. */
2144  fmode = _free(fmode);
2145  fc = rpmfcFree(fc);
2146  av = argvFree(av);
2147 
2148  return rc;
2149 }
2150 
2151 /*@-mustmod@*/
2152 static void rpmfcFini(void * _fc)
2153  /*@modifies _fc @*/
2154 {
2155  rpmfc fc = (rpmfc) _fc;
2156 
2157  fc->fn = argvFree(fc->fn);
2158  fc->fcolor = argiFree(fc->fcolor);
2159  fc->fcdictx = argiFree(fc->fcdictx);
2160  fc->fddictx = argiFree(fc->fddictx);
2161  fc->fddictn = argiFree(fc->fddictn);
2162  fc->cdict = argvFree(fc->cdict);
2163  fc->ddict = argvFree(fc->ddict);
2164  fc->ddictx = argiFree(fc->ddictx);
2165 
2166  (void)rpmdsFree(fc->provides);
2167  fc->provides = NULL;
2168  (void)rpmdsFree(fc->requires);
2169  fc->requires = NULL;
2170 
2171  fc->iob_java = rpmiobFree(fc->iob_java);
2172  fc->iob_perl = rpmiobFree(fc->iob_perl);
2173  fc->iob_python = rpmiobFree(fc->iob_python);
2174  fc->iob_php = rpmiobFree(fc->iob_php);
2175 }
2176 /*@=mustmod@*/
2177 
2178 /*@unchecked@*/ /*@only@*/ /*@null@*/
2180 
2181 static rpmfc rpmfcGetPool(/*@null@*/ rpmioPool pool)
2182  /*@globals _rpmfcPool, fileSystem, internalState @*/
2183  /*@modifies pool, _rpmfcPool, fileSystem, internalState @*/
2184 {
2185  rpmfc fc;
2186 
2187  if (_rpmfcPool == NULL) {
2188  _rpmfcPool = rpmioNewPool("fc", sizeof(*fc), -1, _rpmfc_debug,
2189  NULL, NULL, rpmfcFini);
2190  pool = _rpmfcPool;
2191  }
2192  fc = (rpmfc) rpmioGetPool(pool, sizeof(*fc));
2193  memset(((char *)fc)+sizeof(fc->_item), 0, sizeof(*fc)-sizeof(fc->_item));
2194  return fc;
2195 }
2196 
2198 {
2199  rpmfc fc = rpmfcGetPool(_rpmfcPool);
2200  fc->fn = (ARGV_t) xcalloc(1, sizeof(*fc->fn));
2201  return rpmfcLink(fc);
2202 }
2203 
int rpmdsNext(rpmds ds)
Return next dependency set iterator index.
Definition: rpmds.c:912
rpmuint32_t rpmfiFFlags(rpmfi fi)
Return current file flags from file info set.
Definition: rpmfi.c:217
rpmTagType t
Definition: rpmtag.h:502
int rpmEVRcompare(const EVR_t a, const EVR_t b)
Compare EVR containers for equality.
Definition: rpmevr.c:280
rpmiob rpmiobRTrim(rpmiob iob)
Trim trailing white space.
Definition: rpmiob.c:67
const char * str
Definition: rpmtag.h:73
int xx
Definition: spec.c:744
rpmTag tag
Definition: rpmtag.h:501
iter fi
Definition: fsm.c:170
const char ** argv
Definition: rpmtag.h:75
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
rpmlog(RPMLOG_ERR,"%s\n", buf)
static struct rpmfcApplyTbl_s rpmfcApplyTable[]
XXX Having two entries for rpmfcSCRIPT may be unnecessary duplication.
Definition: rpmfc.c:1082
#define RPMELF_FLAG_SKIPREQUIRES
Definition: rpmds.h:621
return se
Definition: macro.c:897
static DepMsg_t ScriptMsgs
Definition: rpmfc.c:1685
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:2152
static int rpmfcMatchRegexps(void *_mire, int nmire, const char *str, char deptype)
Definition: rpmfc.c:377
struct DepMsg_s * DepMsg_t
Definition: rpmfc.c:1471
#define EXIT_FAILURE
static void printDeps(Header h)
Print dependencies in a header.
Definition: rpmfc.c:1536
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
int headerMod(Header h, HE_t he, unsigned int flags)
Modify tag container in header.
Definition: header.c:2318
const char * rootURL
Definition: rpmspec.h:120
int rpmdsFind(rpmds ds, const rpmds ods)
Find a dependency set element using binary search.
Definition: rpmds.c:998
Structure(s) used for file info tag sets.
int rc
Definition: poptALL.c:670
evrFlags rpmdsFlags(const rpmds ds)
Return current dependency flags.
Definition: rpmds.c:691
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
int rpmdsMerge(rpmds *dsp, rpmds ods)
Merge a dependency set maintaining (N,EVR,Flags) sorted order.
Definition: rpmds.c:1030
rpmioPool _rpmfcPool
Definition: poptALL.c:570
enum rpmTag_e rpmTag
Definition: rpmtag.h:468
static int rpmfcELF(rpmfc fc)
Extract Elf dependencies.
Definition: rpmfc.c:1026
int errno
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.
struct EVR_s * EVR_t
Definition: rpmevr.h:22
rpmRC rpmfcApply(rpmfc fc)
Build file/package dependency dictionary and mappings.
Definition: rpmfc.c:1092
EVR_t rpmEVRnew(uint32_t Flags, int initialize)
Create a new EVR container.
Definition: rpmevr.c:31
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
rpmds rpmdsNew(Header h, rpmTag tagN, int flags)
Create and load a dependency set.
Definition: rpmds.c:238
int ac
Definition: rpmgrep.c:1431
Header h
Definition: spec.c:739
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
argv
Definition: rpmmtree.c:3679
int argiCount(ARGI_t argi)
Return no.
Definition: argv.c:55
int rpmfiFC(rpmfi fi)
Return file count from file info set.
Definition: rpmfi.c:87
static PyObject *char * mode
Definition: rpmfd-py.c:115
int rpmEVRparse(const char *evrstr, EVR_t evr)
Split EVR string into epoch, version, and release components.
Definition: rpmevr.c:181
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:60
char * argvJoin(ARGV_t argv, char sep)
Concatenate an argv array into a string.
Definition: argv.c:274
sprintf(t," (%u)",(unsigned) dig->nbytes)
const char * N
Definition: rpmds.c:2714
enum evrFlags_e evrFlags
Dependency Attributes.
int toggle
Definition: rpmfc.c:1484
char * alloca()
enum rpmRC_e rpmRC
RPM return codes.
Definition: signature.c:616
Yet Another syslog(3) API clone.
goto exit
Definition: db3.c:1903
memset(_r, 0, sizeof(*_r))
static struct rpmfcTokens_s rpmfcTokens[]
Definition: rpmfc.c:572
Header header
Definition: rpmspec.h:217
static rpmfc rpmfcGetPool(rpmioPool pool)
Definition: rpmfc.c:2181
int headerDel(Header h, HE_t he, unsigned int flags)
Remove tag container from header.
Definition: header.c:2312
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
miRE mireFree(miRE mire)
Free pattern container.
const char * argv[4]
Definition: rpmfc.c:1479
struct Package_s * Package
Definition: rpmspec.h:20
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
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
assert(key->size==sizeof(hdrNum))
void * ptr
Definition: rpmtag.h:67
int ix
Definition: rpmps-py.c:174
int rpmdsSetIx(rpmds ds, int ix)
Set dependency set index.
Definition: rpmds.c:646
rpmfc rpmfcLink(rpmfc fc)
Reference a file classifier instance.
HE_t ec
Definition: hdrfmt.c:6710
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
int rpmdsSearch(rpmds ds, rpmds ods)
Search a sorted dependency set for an element that overlaps.
Definition: rpmds.c:1108
rpmfc rpmfcFree(rpmfc fc)
Destroy a file classifier.
rpmTag vtag
Definition: rpmfc.c:1481
static DepMsg_t DepMsgs
Definition: rpmfc.c:1530
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
rpmTag rpmdsTagN(const rpmds ds)
Return current dependency type.
Definition: rpmds.c:702
enum evrFlags_e rpmsenseFlags
Definition: rpmevr.h:74
int rpmdsMatch(const rpmds A, rpmds B)
Compare A against every member of B, looking for 1st match.
Definition: rpmds.c:4169
he tag
Definition: db3.c:1927
rpmTagData p
Definition: rpmtag.h:504
static int rpmfcMergePR(void *context, rpmds ds)
Merge provides/requires dependencies into a rpmfc container.
Definition: rpmfc.c:977
static unsigned removeSillyDeps(Header h, rpmfc fc)
Definition: rpmfc.c:1760
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:122
int rpmfcExec(ARGV_t av, rpmiob iob_stdin, rpmiob *iob_stdoutp, int failnonzero)
Definition: rpmfc.c:229
const char * tagName(rpmTag tag)
Return tag name from value.
Definition: tagname.c:436
const char * msg
Definition: rpmfc.c:1477
static int _filter_values
Definition: rpmfc.c:39
struct _HE_s * HE_t
Destroy an extension cache.
Definition: rpmtag.h:59
Structure(s) used for dependency tag sets.
key
Definition: macro.c:383
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2230
int autoProv
Definition: rpmspec.h:224
rpmTag ftag
Definition: rpmfc.c:1482
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2293
rpmRC(* _parseRCPOT)(Spec spec, Package pkg, const char *field, rpmTag tagN, rpmuint32_t index, rpmsenseFlags tagflags)
Definition: rpmspec.h:179
int rpmdsCount(const rpmds ds)
Return dependency set count.
Definition: rpmds.c:636
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:3417
return k val
Definition: rpmmtree.c:401
int argvAdd(ARGV_t *argvp, ARGstr_t val)
Add a string to an argv array.
Definition: argv.c:199
rpmTagCount c
Definition: rpmtag.h:505
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&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3178
static struct DepMsg_s scriptMsgs[]
Definition: rpmfc.c:1667
int Chdir(const char *path)
chdir(2) clone.
Definition: rpmrpc.c:105
void rpmfcPrint(const char *msg, rpmfc fc, FILE *fp)
Print results of file classification.
Definition: rpmfc.c:694
int(* func)(rpmfc fc)
Definition: rpmfc.c:1073
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:1491
static int rpmfcSCRIPT(rpmfc fc)
Extract script dependencies.
Definition: rpmfc.c:776
spectags st
Definition: spec.c:741
int j
Definition: spec.c:743
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
struct rpmds_s * rpmds
Dependency tag sets from a header, so that a header can be discarded early.
Definition: rpmtypes.h:28
enum rpmfileAttrs_e rpmfileAttrs
File Attributes.
int rpmfiNext(rpmfi fi)
Return next file iterator index.
Definition: rpmfi.c:526
rpmds rpmdsFree(rpmds ds)
Destroy a dependency set.
#define S_IFSOCK
Definition: system.h:647
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:112
Definition: rpmtag.h:500
rpmfi rpmfiInit(rpmfi fi, int fx)
Initialize file iterator index.
Definition: rpmfi.c:548
const char * buildRootURL
Definition: spec-py.c:63
EVR_t rpmEVRfree(EVR_t evr)
Destroy an EVR container.
Definition: rpmevr.c:47
return strcmp(ame->name, bme->name)
const char * s
Definition: poptALL.c:734
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
This is the only module users of librpmbuild should need to include.
struct rpmmg_s * rpmmg
Definition: rpmmg.h:15
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:1311
char * stpcpy(char *dest, const char *src)
if(__progname==NULL)
Definition: poptALL.c:683
static rpmRC rpmfcGenerateDependsHelper(const Spec spec, Package pkg, rpmfi fi)
Definition: rpmfc.c:1584
rpmds rpmdsInit(rpmds ds)
Initialize dependency set iterator.
Definition: rpmds.c:943
static int rpmfcGenerateScriptletDeps(const Spec spec, Package pkg)
Definition: rpmfc.c:1689
#define _suffix(_s, _x)
int flags
Definition: fnmatch.c:282
const char * rpmdsEVR(const rpmds ds)
Return current dependency epoch-version-release.
Definition: rpmds.c:680
const char * rpmdsDNEVR(const rpmds ds)
Return current formatted dependency string.
Definition: rpmds.c:657
const char * msg
Definition: rpmts-py.c:976
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
int mask
Definition: rpmfc.c:1483
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
return NULL
Definition: poptALL.c:613
rpmiob rpmiobEmpty(rpmiob iob)
Empty an I/O buffer.
Definition: rpmiob.c:57
struct Spec_s * Spec
Definition: rpmtypes.h:23
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
static void
Print copy of spec file, filling in Group/Description/Summary from specspo.
Definition: spec.c:737
char * buf
Parse (and execute) macro undefinition.
Definition: macro.c:703
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
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:2935
int
Save source and expand field into target.
Definition: rpmds.c:2709
status
Definition: rpmsq.c:792
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:83
const char * rpmdsN(const rpmds ds)
Return current dependency name.
Definition: rpmds.c:668
#define RPMELF_FLAG_SKIPPROVIDES
Definition: rpmds.h:620
rpmRC rpmfcGenerateDepends(void *_spec, void *_pkg)
Generate package dependencies.
Definition: rpmfc.c:1882
ARGstr_t * ARGV_t
Definition: argv.h:12
rpmfi fi
Definition: rpmspec.h:221
char * EVR
Definition: rpmds.c:2715
#define D_(Text)
Definition: system.h:526
static int _filter_execs
Definition: rpmfc.c:41
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
evrFlags Flags
Definition: rpmds.c:2717
int i
Definition: spec.c:743
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:3252
const char ** av
Definition: rpmts-py.c:788
struct rpmfc_s * rpmfc
Definition: rpmfc.h:11
#define xrealloc
Definition: system.h:35
size_t fn
Definition: macro.c:1698
rpmmg rpmmgFree(rpmmg mg)
Destroy a magic wrapper.
rpmfc rpmfcNew(void)
Create a file classifier.
Definition: rpmfc.c:2197
#define RPMFC_ELF
Definition: rpmfc.h:24
static PyObject *rpmds ds
Definition: rpmte-py.c:283
int autoReq
Definition: rpmspec.h:223
Spec spec
Definition: spec-py.c:121
rpmTag ntag
Definition: rpmfc.c:1480
static void * rpmfcExpandRegexps(const char *str, int *nmirep)
Definition: rpmfc.c:334