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