rpm  5.4.10
reqprov.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio.h>
9 #include <rpmiotypes.h>
10 #define _RPMEVR_INTERNAL
11 #include "rpmbuild.h"
12 #include <rpmds.h>
13 #include <rpmlog.h>
14 #include "debug.h"
15 
16 int addReqProv(/*@unused@*/ Spec spec, Header h,
17  /*@unused@*/ rpmTag tagN,
18  const char * N, const char * EVR, rpmsenseFlags Flags,
19  rpmuint32_t index)
20 {
21  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
22  const char ** names;
23  rpmTag nametag = 0;
24  rpmTag versiontag = 0;
25  rpmTag flagtag = 0;
26  rpmTag indextag = 0;
27  int len;
28  rpmsenseFlags extra = RPMSENSE_ANY;
29  int xx;
30 
31  if (Flags & RPMSENSE_PROVIDES) {
32  nametag = RPMTAG_PROVIDENAME;
33  versiontag = RPMTAG_PROVIDEVERSION;
34  flagtag = RPMTAG_PROVIDEFLAGS;
35  extra = Flags & RPMSENSE_FIND_PROVIDES;
36  } else if (Flags & RPMSENSE_OBSOLETES) {
37  nametag = RPMTAG_OBSOLETENAME;
38  versiontag = RPMTAG_OBSOLETEVERSION;
39  flagtag = RPMTAG_OBSOLETEFLAGS;
40  } else if (Flags & RPMSENSE_CONFLICTS) {
41  nametag = RPMTAG_CONFLICTNAME;
42  versiontag = RPMTAG_CONFLICTVERSION;
43  flagtag = RPMTAG_CONFLICTFLAGS;
44  } else if (Flags & RPMSENSE_TRIGGER) {
45  nametag = RPMTAG_TRIGGERNAME;
46  versiontag = RPMTAG_TRIGGERVERSION;
47  flagtag = RPMTAG_TRIGGERFLAGS;
48  indextag = RPMTAG_TRIGGERINDEX;
49  extra = Flags & RPMSENSE_TRIGGER;
50  } else {
51 #if defined(RPM_VENDOR_MANDRIVA)
52  if (!strcmp(N, "/bin/sh") || !strcmp(N, "/sbin/ldconfig")) {
53  rpmlog(RPMLOG_DEBUG, "%s will be satisfied by glibc or it's dependencies, won't add dependency to package\n", N);
54  return 0;
55  }
56 #endif
57  nametag = RPMTAG_REQUIRENAME;
58  versiontag = RPMTAG_REQUIREVERSION;
59  flagtag = RPMTAG_REQUIREFLAGS;
60  extra = Flags & _ALL_REQUIRES_MASK;
61  }
62 
63  Flags = (Flags & RPMSENSE_SENSEMASK) | extra;
64 
65  if (EVR == NULL)
66  EVR = "";
67 #if defined(RPM_VENDOR_MANDRIVA)
68  /* Check that provide isn't duplicate of package */
69  else if (nametag == RPMTAG_PROVIDENAME) {
70  const char *NEVR;
71  size_t len;
72  int duplicate;
73 
74  len = strlen(N);
75  NEVR = headerSprintf(h, "%{NAME}-%|EPOCH?{%{EPOCH}:}|%{VERSION}-%{RELEASE}", NULL, NULL, NULL);
76  duplicate = !strncmp(NEVR, N, len) && !strcmp(NEVR+len+1, EVR);
77 
78  _free(NEVR);
79 
80  if (duplicate)
81  return 0;
82  }
83 #endif
84 
85  /* Check for duplicate dependencies. */
86  he->tag = nametag;
87  xx = headerGet(h, he, 0);
88  names = he->p.argv;
89  len = he->c;
90  if (xx) {
91  const char ** versions = NULL;
92  rpmuint32_t * flags = NULL;
93  rpmuint32_t * indexes = NULL;
94  int duplicate = 0;
95 
96  if (flagtag) {
97  he->tag = versiontag;
98  xx = headerGet(h, he, 0);
99  versions = he->p.argv;
100  he->tag = flagtag;
101  xx = headerGet(h, he, 0);
102  flags = he->p.ui32p;
103  }
104  if (indextag) {
105  he->tag = indextag;
106  xx = headerGet(h, he, 0);
107  indexes = he->p.ui32p;
108  }
109 
110  while (len > 0) {
111  len--;
112  if (strcmp(names[len], N))
113  continue;
114 
115 #if defined(RPM_VENDOR_MANDRIVA) /* filter-overlapping-dependencies */
116  /* XXX: Potential drawbacks? Need to study & discuess this one a
117  * bit further, leaving under #ifdef for now...
118  * TODO: auto-generated deps too
119  */
120  if (Flags & RPMSENSE_TRIGGER)
121  continue;
122 
123  if (flagtag && versions != NULL) {
124  int overlap = 0, res = 0;
125  rpmds old = rpmdsSingle(flagtag, names[len], versions[len] ? versions[len] : "", flags[len]);
126  rpmds new = rpmdsSingle(flagtag, N, EVR, Flags);
127 
128  /* do not consider dependency ranges like R: foo > 1, R: foo < 3
129  * as overlapping (mdvbz#65269)
130  */
131 #define RPMSENSE_SCRIPTS (RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_POST|RPMSENSE_SCRIPT_PREUN|RPMSENSE_SCRIPT_POSTUN|RPMSENSE_SCRIPT_VERIFY)
132  if (!((Flags & RPMSENSE_GREATER && flags[len] & RPMSENSE_LESS) ||
133  (Flags & RPMSENSE_LESS && flags[len] & RPMSENSE_GREATER)) &&
134  /* R: foo >= 1 cannot overlap R: foo <= 1*/
135  !(((Flags & RPMSENSE_GREATER) && (flags[len] & RPMSENSE_LESS)) ||
136  ((flags[len] & RPMSENSE_GREATER) && (Flags & RPMSENSE_LESS))) &&
137  /* do not merge script dependencies with non-script dependencies */
138  !(((Flags & RPMSENSE_SCRIPTS) && !(flags[len] & RPMSENSE_SCRIPTS)) ||
139  ((flags[len] & RPMSENSE_SCRIPTS) && !(Flags & RPMSENSE_SCRIPTS))))
140  overlap = rpmdsCompare(new, old);
141 #undef RPMSENSE_SCRIPTS
142  if (overlap) {
143  EVR_t lEVR = rpmEVRnew(RPMSENSE_ANY, 0),
144  rEVR = rpmEVRnew(RPMSENSE_ANY, 0);
145  rpmuint32_t newflags;
146  /* if we have both a requires and suggests, we turn it into a requires */
147  if (!(Flags & RPMSENSE_MISSINGOK) || !(flags[len] & RPMSENSE_MISSINGOK)) {
148  flags[len] &= ~RPMSENSE_MISSINGOK;
149  Flags &= ~RPMSENSE_MISSINGOK;
150  }
151 
152  /* merge all flags about dependency type */
153  newflags = ((flags[len]| Flags) & _ALL_REQUIRES_MASK);
154 
155  rpmEVRparse(EVR, lEVR);
156  rpmEVRparse(versions[len], rEVR);
157  lEVR->Flags = Flags;
158  rEVR->Flags = flags[len];
159 
160  res = rpmEVRcompare(lEVR, rEVR);
161  /* we only update version if greater */
162  if (res > 0) {
163  flags[len] = Flags;
164 
165  versions[len] = EVR;
166  he->tag = versiontag;
167  he->t = RPM_STRING_ARRAY_TYPE;
168  he->p.argv = versions;
169  xx = headerMod(h, he, 0);
170  rpmlog(RPMLOG_WARNING, "%s overlaps %s, removing %s\n", rpmdsDNEVR(old), rpmdsDNEVR(new), rpmdsDNEVR(old));
171  } else if (res < 0)
172  rpmlog(RPMLOG_WARNING, "%s overlaps %s, removing %s\n", rpmdsDNEVR(new), rpmdsDNEVR(old), rpmdsDNEVR(new));
173  else if (flags[len] != Flags) {
174  if (((Flags & RPMSENSE_SENSEMASK) == RPMSENSE_EQUAL && (flags[len] & (RPMSENSE_GREATER|RPMSENSE_LESS))))
175  flags[len] &= ~(RPMSENSE_GREATER|RPMSENSE_LESS);
176  rpmlog(RPMLOG_WARNING, "%s overlaps %s, removing %s and merging flags\n", rpmdsDNEVR(new), rpmdsDNEVR(old), rpmdsDNEVR(new));
177  }
178 
179  flags[len] |= newflags;
180  he->tag = flagtag;
181  he->t = RPM_UINT32_TYPE;
182  he->p.ui32p = flags;
183  xx = headerMod(h, he, 0);
184 
185  lEVR = rpmEVRfree(lEVR);
186  rEVR = rpmEVRfree(rEVR);
187  duplicate = 1;
188  }
189  old = rpmdsFree(old);
190  new = rpmdsFree(new);
191 
192  if (!overlap)
193  continue;
194  }
195 #else
196  if (flagtag && versions != NULL &&
197  (strcmp(versions[len], EVR) || (rpmsenseFlags)flags[len] != Flags))
198  continue;
199 #endif
200 
201  if (indextag && indexes != NULL && indexes[len] != index)
202  continue;
203 
204  /* This is a duplicate dependency. */
205  duplicate = 1;
206 
207  break;
208  }
209 /*@-usereleased@*/
210  names = _free(names);
211  versions = _free(versions);
212  flags = _free(flags);
213  indexes = _free(indexes);
214 /*@=usereleased@*/
215  if (duplicate)
216  return 0;
217  }
218 
219  /* Add this dependency. */
220  he->tag = nametag;
221  he->t = RPM_STRING_ARRAY_TYPE;
222  he->p.argv = &N;
223  he->c = 1;
224  he->append = 1;
225  xx = headerPut(h, he, 0);
226  he->append = 0;
227 
228  if (flagtag) {
229  he->tag = versiontag;
230  he->t = RPM_STRING_ARRAY_TYPE;
231  he->p.argv = &EVR;
232  he->c = 1;
233  he->append = 1;
234  xx = headerPut(h, he, 0);
235  he->append = 0;
236 
237  he->tag = flagtag;
238  he->t = RPM_UINT32_TYPE;
239  he->p.ui32p = (void *) &Flags;
240  he->c = 1;
241  he->append = 1;
242  xx = headerPut(h, he, 0);
243  he->append = 0;
244  }
245  if (indextag) {
246  he->tag = indextag;
247  he->t = RPM_UINT32_TYPE;
248  he->p.ui32p = &index;
249  he->c = 1;
250  he->append = 1;
251  xx = headerPut(h, he, 0);
252  he->append = 0;
253  }
254 
255  return 0;
256 }
257 
258 int rpmlibNeedsFeature(Header h, const char * feature, const char * featureEVR)
259 {
260  char * reqname = alloca(sizeof("rpmlib()") + strlen(feature));
261 
262  (void) stpcpy( stpcpy( stpcpy(reqname, "rpmlib("), feature), ")");
263 
264  /* XXX 1st arg is unused */
265  return addReqProv(NULL, h, RPMTAG_REQUIRENAME, reqname, featureEVR,
266  RPMSENSE_RPMLIB|(RPMSENSE_LESS|RPMSENSE_EQUAL), 0);
267 }
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:505
rpmTag tag
Definition: rpmtag.h:504
const char ** argv
Definition: rpmtag.h:74
#define RPMSENSE_SENSEMASK
Definition: rpmevr.h:74
rpmuint32_t * ui32p
Definition: rpmtag.h:69
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2222
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2285
int addReqProv(Spec spec, Header h, rpmTag tagN, const char *N, const char *EVR, rpmsenseFlags Flags, rpmuint32_t index)
Add dependency to header, filtering duplicates.
Definition: reqprov.c:16
The Header data structure.
int rpmEVRparse(const char *evrstr, EVR_t evr)
Split EVR string into epoch, version, and release components.
Definition: rpmevr.c:179
struct EVR_s * EVR_t
Definition: rpmevr.h:20
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
const char * rpmdsDNEVR(const rpmds ds)
Return current formatted dependency string.
Definition: rpmds.c:657
struct rpmds_s * rpmds
Dependency tag sets from a header, so that a header can be discarded early.
Definition: rpmtypes.h:28
rpmds rpmdsFree(rpmds ds)
Destroy a dependency set.
char * headerSprintf(Header h, const char *fmt, headerTagTableEntry tags, headerSprintfExtension exts, errmsg_t *errmsg)
Return formatted output string from header tags.
Definition: hdrfmt.c:6700
int rpmEVRcompare(const EVR_t a, const EVR_t b)
Compare EVR containers for equality.
Definition: rpmevr.c:274
char * alloca()
Yet Another syslog(3) API clone.
int headerMod(Header h, HE_t he, unsigned int flags)
Modify tag container in header.
Definition: header.c:2310
unsigned int rpmuint32_t
Definition: rpmiotypes.h:25
struct _HE_s * HE_t
Definition: rpmtag.h:58
int rpmdsCompare(const rpmds A, const rpmds B)
Compare two versioned dependency ranges, looking for overlap.
Definition: rpmds.c:4347
enum evrFlags_e rpmsenseFlags
Definition: rpmevr.h:72
rpmTagData p
Definition: rpmtag.h:507
Structure(s) used for dependency tag sets.
rpmTagCount c
Definition: rpmtag.h:508
The structure used to store values parsed from a spec file.
Definition: rpmspec.h:108
EVR_t rpmEVRnew(uint32_t Flags, int initialize)
Create a new EVR container.
Definition: rpmevr.c:31
Definition: rpmtag.h:503
EVR_t rpmEVRfree(EVR_t evr)
Destroy an EVR container.
Definition: rpmevr.c:47
This is the only module users of librpmbuild should need to include.
char * stpcpy(char *dest, const char *src)
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
enum rpmTag_e rpmTag
Definition: rpmtag.h:471
int rpmlibNeedsFeature(Header h, const char *feature, const char *featureEVR)
Add rpmlib feature dependency.
Definition: reqprov.c:258
unsigned int append
Definition: rpmtag.h:512