#include <argv.h>
#include <rpmfc.h>
+#define _RPMDS_INTERNAL
#include <rpmds.h>
#include <rpmfi.h>
#include "debug.h"
/*@access fmagic @*/
+/*@access rpmds @*/
/*@unchecked@*/
int _rpmfc_debug;
return rc;
}
+static char * rpmfcFileDep(char * buf, int ix, rpmds this)
+ /*@modifies buf @*/
+{
+ int_32 tagN = rpmdsTagN(this);
+ char deptype = 'X';
+
+ switch (tagN) {
+ case RPMTAG_PROVIDENAME:
+ deptype = 'P';
+ break;
+ case RPMTAG_REQUIRENAME:
+ deptype = 'R';
+ break;
+ }
+ sprintf(buf, "%08d%c %s %s 0x%08x", ix, deptype,
+ rpmdsN(this), rpmdsEVR(this), rpmdsFlags(this));
+ return buf;
+};
+
/**
* Run per-interpreter dependency helper.
* @param fc file classifier
StringBuf sb_stdout = NULL;
StringBuf sb_stdin;
const char *av[2];
- ARGV_t * depsp;
+ rpmds * depsp, this;
+ const char * N;
+ const char * EVR;
+ int_32 Flags, dsContext, tagN;
ARGV_t pav;
+ const char * s;
int pac;
int xx;
int i;
- size_t ns;
- char * t;
switch (deptype) {
default:
case 'P':
xx = snprintf(buf, sizeof(buf), "%%{?__%s_provides}", nsdep);
depsp = &fc->provides;
+ dsContext = RPMSENSE_FIND_PROVIDES;
+ tagN = RPMTAG_PROVIDENAME;
break;
case 'R':
xx = snprintf(buf, sizeof(buf), "%%{?__%s_requires}", nsdep);
depsp = &fc->requires;
+ dsContext = RPMSENSE_FIND_REQUIRES;
+ tagN = RPMTAG_REQUIRENAME;
break;
}
buf[sizeof(buf)-1] = '\0';
pac = argvCount(pav);
if (pav)
for (i = 0; i < pac; i++) {
- t = buf;
- *t = '\0';
- t = stpcpy(t, pav[i]);
- if (pav[i+1] && strchr("!=<>", *pav[i+1])) {
+ N = pav[i];
+ EVR = "";
+ Flags = dsContext;
+ if (pav[i+1] && strchr("=<>", *pav[i+1])) {
i++;
- *t++ = ' ';
- t = stpcpy(t, pav[i]);
- if (pav[i+1]) {
- i++;
- *t++ = ' ';
- t = stpcpy(t, pav[i]);
+ for (s = pav[i]; *s; s++) {
+ switch(*s) {
+ default:
+assert(*s != '\0');
+ /*@switchbreak@*/ break;
+ case '=':
+ Flags |= RPMSENSE_EQUAL;
+ /*@switchbreak@*/ break;
+ case '<':
+ Flags |= RPMSENSE_LESS;
+ /*@switchbreak@*/ break;
+ case '>':
+ Flags |= RPMSENSE_GREATER;
+ /*@switchbreak@*/ break;
+ }
}
+ i++;
+ EVR = pav[i];
+assert(EVR != NULL);
}
- ns = strlen(buf);
- /* Add to package dependencies. */
- xx = rpmfcSaveArg(depsp, buf);
+ this = rpmdsSingle(tagN, N, EVR, Flags);
+ xx = rpmdsMerge(depsp, this);
/* Add to file dependencies. */
- if (ns < (sizeof(buf) - ns - 64)) {
- t = buf + ns + 1;
- *t = '\0';
- sprintf(t, "%08d%c %s", fc->ix, deptype, buf);
- xx = rpmfcSaveArg(&fc->ddict, t);
- }
+ xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(buf, fc->ix, this));
+
+ this = rpmdsFree(this);
}
pav = argvFree(pav);
if (msg)
fprintf(fp, "===================================== %s\n", msg);
-nprovides = argvCount(fc->provides);
-nrequires = argvCount(fc->requires);
+nprovides = rpmdsCount(fc->provides);
+nrequires = rpmdsCount(fc->requires);
if (fc)
for (fx = 0; fx < fc->nfiles; fx++) {
/*@switchbreak@*/ break;
case 'P':
assert(ix < nprovides);
- depval = fc->provides[ix];
+ (void) rpmdsSetIx(fc->provides, ix);
+ depval = rpmdsDNEVR(fc->provides);
/*@switchbreak@*/ break;
case 'R':
assert(ix < nrequires);
- depval = fc->requires[ix];
+ (void) rpmdsSetIx(fc->requires, ix);
+ depval = rpmdsDNEVR(fc->requires);
/*@switchbreak@*/ break;
}
if (depval)
- fprintf(fp, "\t%c %s\n", deptype, depval);
+ fprintf(fp, "\t%s\n", depval);
}
}
}
fc->fddictn = argiFree(fc->fddictn);
fc->ddict = argvFree(fc->ddict);
fc->ddictx = argiFree(fc->ddictx);
- fc->provides = argvFree(fc->provides);
- fc->requires = argvFree(fc->requires);
+ fc->provides = rpmdsFree(fc->provides);
+ fc->requires = rpmdsFree(fc->requires);
}
fc = _free(fc);
return NULL;
{
const char * fn = fc->fn[fc->ix];
const char * bn;
- unsigned char deptype;
+ rpmds this;
char buf[BUFSIZ];
FILE * fp;
char * s, * se;
- size_t ns;
- char * t;
int i;
struct stat sb, * st = &sb;
int xx;
}
/* Look for #! interpreter in first 10 lines. */
- deptype = 'R';
for (i = 0; i < 10; i++) {
s = fgets(buf, sizeof(buf) - 1, fp);
if (s == NULL || ferror(fp) || feof(fp))
break;
s[sizeof(buf)-1] = '\0';
- ns = strlen(s);
if (!(s[0] == '#' && s[1] == '!'))
continue;
s += 2;
/*@innerbreak@*/ break;
}
*se = '\0';
+ se++;
/* Add to package requires. */
- xx = rpmfcSaveArg(&fc->requires, s);
+ this = rpmdsSingle(RPMTAG_REQUIRENAME, s, "", RPMSENSE_FIND_REQUIRES);
+ xx = rpmdsMerge(&fc->requires, this);
/* Add to file requires. */
- if (ns < (sizeof(buf) - ns - 64)) {
- t = se + 1;
- *t = '\0';
- sprintf(t, "%08d%c %s", fc->ix, deptype, s);
- xx = rpmfcSaveArg(&fc->ddict, t);
- }
+ xx = rpmfcSaveArg(&fc->ddict, rpmfcFileDep(se, fc->ix, this));
+
+ this = rpmdsFree(this);
/* Set color based on interpreter name. */
bn = basename(s);
const char * s;
unsigned char deptype;
const char * soname = NULL;
- ARGV_t * depsp;
- const char * depval;
+ rpmds * depsp, this;
+ int_32 tagN, dsContext;
char * t;
int xx;
int isElf64;
} else if (soname != NULL) {
buf[0] = '\0';
t = buf;
- sprintf(t, "%08d%c ", fc->ix, deptype);
- t += strlen(t);
- depval = t;
t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
#if !defined(__alpha__)
if (isElf64)
t = stpcpy(t, "(64bit)");
#endif
+ t++;
/* Add to package provides. */
- xx = rpmfcSaveArg(&fc->provides, depval);
+ this = rpmdsSingle(RPMTAG_PROVIDES,
+ buf, "", RPMSENSE_FIND_PROVIDES);
+ xx = rpmdsMerge(&fc->provides, this);
/* Add to file dependencies. */
- xx = rpmfcSaveArg(&fc->ddict, buf);
+ xx = rpmfcSaveArg(&fc->ddict,
+ rpmfcFileDep(t, fc->ix, this));
+
+ this = rpmdsFree(this);
}
auxoffset += aux->vda_next;
}
if (soname != NULL) {
buf[0] = '\0';
t = buf;
- sprintf(t, "%08d%c ", fc->ix, deptype);
- t += strlen(t);
- depval = t;
t = stpcpy( stpcpy( stpcpy( stpcpy(t, soname), "("), s), ")");
#if !defined(__alpha__)
if (isElf64)
t = stpcpy(t, "(64bit)");
#endif
+ t++;
- /* Add to package requires. */
- xx = rpmfcSaveArg(&fc->requires, depval);
+ /* Add to package dependencies. */
+ this = rpmdsSingle(RPMTAG_REQUIRENAME,
+ buf, "", RPMSENSE_FIND_REQUIRES);
+ xx = rpmdsMerge(&fc->requires, this);
/* Add to file dependencies. */
- xx = rpmfcSaveArg(&fc->ddict, buf);
+ xx = rpmfcSaveArg(&fc->ddict,
+ rpmfcFileDep(t, fc->ix, this));
+ this = rpmdsFree(this);
}
auxoffset += aux->vna_next;
}
case DT_NEEDED:
/* Add to package requires. */
deptype = 'R';
- s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
depsp = &fc->requires;
+ tagN = RPMTAG_REQUIRENAME;
+ dsContext = RPMSENSE_FIND_REQUIRES;
+ s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
+assert(s != NULL);
/*@switchbreak@*/ break;
case DT_SONAME:
/* Add to package provides. */
deptype = 'P';
depsp = &fc->provides;
+ tagN = RPMTAG_PROVIDENAME;
+ dsContext = RPMSENSE_FIND_PROVIDES;
s = elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val);
+assert(s != NULL);
/*@switchbreak@*/ break;
}
if (s == NULL)
buf[0] = '\0';
t = buf;
- sprintf(t, "%08d%c ", fc->ix, deptype);
- t += strlen(t);
- depval = t;
t = stpcpy(t, s);
#if !defined(__alpha__)
if (isElf64)
t = stpcpy(t, "()(64bit)");
#endif
+ t++;
- /* Add to package requires. */
- xx = rpmfcSaveArg(depsp, depval);
+ /* Add to package dependencies. */
+ this = rpmdsSingle(tagN, buf, "", dsContext);
+ xx = rpmdsMerge(depsp, this);
/* Add to file dependencies. */
- xx = rpmfcSaveArg(&fc->ddict, buf);
+ xx = rpmfcSaveArg(&fc->ddict,
+ rpmfcFileDep(t, fc->ix, this));
+
+ this = rpmdsFree(this);
}
}
/*@switchbreak@*/ break;
{
const char * s;
char * se;
- ARGV_t dav, davbase;
+ rpmds this;
+ const char * N;
+ const char * EVR;
+ int_32 Flags;
rpmfcApplyTbl fcat;
unsigned char deptype;
int nddict;
int previx;
unsigned int val;
+ int dix;
int ix;
int i;
int xx;
assert(se != NULL);
deptype = *se++;
se++;
-
- davbase = NULL;
+ N = se;
+ while (*se && *se != ' ')
+ se++;
+ *se++ = '\0';
+ EVR = se;
+ while (*se && *se != ' ')
+ se++;
+ *se++ = '\0';
+ Flags = strtol(se, NULL, 16);
+
+ dix = -1;
switch (deptype) {
default:
-assert(davbase != NULL);
/*@switchbreak@*/ break;
case 'P':
- davbase = fc->provides;
+ this = rpmdsSingle(RPMTAG_PROVIDENAME, N, EVR, Flags);
+ dix = rpmdsFind(fc->provides, this);
+ this = rpmdsFree(this);
/*@switchbreak@*/ break;
case 'R':
- davbase = fc->requires;
+ this = rpmdsSingle(RPMTAG_REQUIRENAME, N, EVR, Flags);
+ dix = rpmdsFind(fc->requires, this);
+ this = rpmdsFree(this);
/*@switchbreak@*/ break;
}
- dav = argvSearch(davbase, se, NULL);
-assert(dav != NULL);
- val = (deptype << 24) | ((dav - davbase) & 0x00ffffff);
+assert(dix >= 0);
+ val = (deptype << 24) | (dix & 0x00ffffff);
xx = argiAdd(&fc->ddictx, -1, val);
if (previx != ix) {
rpmfi fi = pkg->cpioList;
rpmfc fc = NULL;
rpmds ds;
- const char * DNEVR;
int scareMem = 0;
ARGV_t av;
int ac = rpmfiFC(fi);
av[c] = xstrdup(rpmfiFN(fi));
av[ac] = NULL;
- /* Build file class dictionary. */
fc = rpmfcNew();
- xx = rpmfcClassify(fc, av);
/* Copy (and delete) manually generated dependencies to dictionary. */
ds = rpmdsNew(pkg->header, RPMTAG_PROVIDENAME, scareMem);
- ds = rpmdsInit(ds);
- if (ds != NULL)
- while (rpmdsNext(ds) >= 0) {
- DNEVR = rpmdsDNEVR(ds);
- if (DNEVR == NULL)
- continue;
- xx = rpmfcSaveArg(&fc->provides, DNEVR+2);
- }
+ rpmdsMerge(&fc->provides, ds);
ds = rpmdsFree(ds);
+ xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDENAME);
+ xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDEVERSION);
+ xx = headerRemoveEntry(pkg->header, RPMTAG_PROVIDEFLAGS);
ds = rpmdsNew(pkg->header, RPMTAG_REQUIRENAME, scareMem);
- ds = rpmdsInit(ds);
- if (ds != NULL)
- while (rpmdsNext(ds) >= 0) {
- DNEVR = rpmdsDNEVR(ds);
- if (DNEVR == NULL)
- continue;
- xx = rpmfcSaveArg(&fc->requires, DNEVR+2);
- }
+ rpmdsMerge(&fc->requires, ds);
ds = rpmdsFree(ds);
+ xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIRENAME);
+ xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIREVERSION);
+ xx = headerRemoveEntry(pkg->header, RPMTAG_REQUIREFLAGS);
+
+ /* Build file class dictionary. */
+ xx = rpmfcClassify(fc, av);
/* Build file/package dependency dictionary. */
xx = rpmfcApply(fc);
xx = headerAddEntry(pkg->header, RPMTAG_FILECLASS, RPM_INT32_TYPE,
p, c);
+ /* Add Provides: */
+ if (fc->provides != NULL && (c = fc->provides->Count) > 0) {
+ p = (const void **) fc->provides->N;
+ xx = headerAddEntry(pkg->header, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
+ p, c);
+ p = (const void **) fc->provides->EVR;
+ xx = headerAddEntry(pkg->header, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
+ p, c);
+ p = (const void **) fc->provides->Flags;
+ xx = headerAddEntry(pkg->header, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
+ p, c);
+ }
+
+ /* Add Requires: */
+ if (fc->requires != NULL && (c = fc->requires->Count) > 0) {
+ p = (const void **) fc->requires->N;
+ xx = headerAddEntry(pkg->header, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE,
+ p, c);
+ p = (const void **) fc->requires->EVR;
+ xx = headerAddEntry(pkg->header, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE,
+ p, c);
+ p = (const void **) fc->requires->Flags;
+ xx = headerAddEntry(pkg->header, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE,
+ p, c);
+ }
+
/* Add dependency dictionary(#dependencies) */
- p = (const void **) argvData(fc->ddict);
- c = argvCount(fc->ddict);
+ p = (const void **) argiData(fc->ddictx);
+ c = argiCount(fc->ddictx);
if (p != NULL)
- xx = headerAddEntry(pkg->header, RPMTAG_DEPENDSDICT, RPM_STRING_ARRAY_TYPE,
+ xx = headerAddEntry(pkg->header, RPMTAG_DEPENDSDICT, RPM_INT32_TYPE,
p, c);
/* Add per-file dependency (start,number) pairs (#files) */
/*@=refcounttrans@*/
}
+static const char ** rpmdsDupArgv(const char ** argv, int argc)
+ /*@*/
+{
+ const char ** av;
+ size_t nb = 0;
+ int ac = 0;
+ char * t;
+
+ for (ac = 0; ac < argc; ac++) {
+assert(argv[ac] != NULL);
+ nb += strlen(argv[ac]) + 1;
+ }
+ nb += (ac + 1) * sizeof(*av);
+
+ av = xmalloc(nb);
+ t = (char *) (av + ac + 1);
+ for (ac = 0; ac < argc; ac++) {
+ av[ac] = t;
+ t = stpcpy(t, argv[ac]) + 1;
+ }
+ av[ac] = NULL;
+ return av;
+}
+
+static rpmds rpmdsDup(const rpmds this)
+ /*@*/
+{
+ rpmds ds = xcalloc(1, sizeof(*ds));
+ size_t nb;
+
+ ds->h = (this->h ? headerLink(this->h) : NULL);
+ ds->Type = this->Type;
+ ds->tagN = this->tagN;
+ ds->Count = this->Count;
+ ds->i = this->i;
+ ds->l = this->l;
+ ds->u = this->u;
+
+ nb = (ds->Count+1) * sizeof(*ds->N);
+ ds->N = (ds->h
+ ? memcpy(xmalloc(nb), this->N, nb)
+ : rpmdsDupArgv(this->N, this->Count) );
+ ds->Nt = this->Nt;
+
+ nb = (ds->Count+1) * sizeof(*ds->EVR);
+ ds->EVR = (ds->h
+ ? memcpy(xmalloc(nb), this->EVR, nb)
+ : rpmdsDupArgv(this->EVR, this->Count) );
+ ds->EVRt = this->EVRt;
+
+ nb = (ds->Count * sizeof(*ds->Flags));
+ ds->Flags = (ds->h
+ ? this->Flags
+ : memcpy(xmalloc(nb), this->Flags, nb) );
+ ds->Ft = this->Ft;
+
+ return rpmdsLink(ds, (ds ? ds->Type : NULL));
+
+}
+
+int rpmdsFind(rpmds ds, rpmds this)
+{
+ int comparison;
+
+ ds->l = 0;
+ ds->u = ds->Count;
+ while (ds->l < ds->u) {
+ ds->i = (ds->l + ds->u) / 2;
+
+ comparison = strcmp(this->N[this->i], ds->N[ds->i]);
+ if (comparison == 0)
+ comparison = strcmp(this->EVR[this->i], ds->EVR[ds->i]);
+ if (comparison == 0)
+ comparison = (this->Flags[this->i] - ds->Flags[ds->i]);
+
+ if (comparison < 0)
+ ds->u = ds->i;
+ else if (comparison > 0)
+ ds->l = ds->i + 1;
+ else {
+ return ds->i;
+ }
+ }
+ return -1;
+}
+
+int rpmdsMerge(rpmds * dsp, rpmds this)
+{
+ rpmds ds;
+ const char ** N;
+ const char ** EVR;
+ int_32 * Flags;
+ int j;
+int save;
+
+ if (dsp == NULL || this == NULL)
+ return -1;
+
+ /* If not initialized yet, dup the 1st entry. */
+ if (*dsp == NULL) {
+ save = this->Count;
+ this->Count = 1;
+ *dsp = rpmdsDup(this);
+ this->Count = save;
+ }
+ ds = *dsp;
+
+ /*
+ * Add new entries.
+ */
+save = this->i;
+ this = rpmdsInit(this);
+ while (rpmdsNext(this) >= 0) {
+ /*
+ * If this entry is already present, don't bother.
+ */
+ if (rpmdsFind(ds, this) >= 0)
+ continue;
+
+ /*
+ * Insert new entry.
+ */
+ for (j = ds->Count; j > ds->u; j--)
+ ds->N[j] = ds->N[j-1];
+ ds->N[ds->u] = this->N[this->i];
+ N = rpmdsDupArgv(ds->N, ds->Count+1);
+ ds->N = _free(ds->N);
+ ds->N = N;
+
+ for (j = ds->Count; j > ds->u; j--)
+ ds->EVR[j] = ds->EVR[j-1];
+ ds->EVR[ds->u] = this->EVR[this->i];
+ EVR = rpmdsDupArgv(ds->EVR, ds->Count+1);
+ ds->EVR = _free(ds->EVR);
+ ds->EVR = EVR;
+
+ Flags = xmalloc((ds->Count+1) * sizeof(*Flags));
+ if (ds->u > 0)
+ memcpy(Flags, ds->Flags, ds->u * sizeof(*Flags));
+ if (ds->u < ds->Count)
+ memcpy(Flags + ds->u + 1, ds->Flags + ds->u, (ds->Count - ds->u) * sizeof(*Flags));
+ Flags[ds->u] = this->Flags[this->i];
+ ds->Flags = _free(ds->Flags);
+ ds->Flags = Flags;
+
+ ds->i = ds->Count;
+ ds->Count++;
+
+ }
+this->i = save;
+ return 0;
+}
+
/**
* Split EVR into epoch, version, and release components.
* @param evr [epoch:]version[-release] string