summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2018-11-30 12:40:36 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2018-11-30 12:40:36 +0900
commit97330b5a608c2213fdf3f49bfbaa268bf9627920 (patch)
treeeb753c0b9543739bb05137b73562d705d0ce8c6f /ext
parente197f682d93362b26879b545062694a050a4c4b4 (diff)
downloadlibsolv-97330b5a608c2213fdf3f49bfbaa268bf9627920.tar.gz
libsolv-97330b5a608c2213fdf3f49bfbaa268bf9627920.tar.bz2
libsolv-97330b5a608c2213fdf3f49bfbaa268bf9627920.zip
Imported Upstream version 0.6.27upstream/0.6.27
Change-Id: I4feccd10bd9fe0514ff13520136e962b6c093175 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'ext')
-rw-r--r--ext/CMakeLists.txt10
-rw-r--r--ext/pool_fileconflicts.c2
-rw-r--r--ext/repo_appdata.c293
-rw-r--r--ext/repo_comps.c225
-rw-r--r--ext/repo_content.c2
-rw-r--r--ext/repo_cudf.c1
-rw-r--r--ext/repo_deltainfoxml.c216
-rw-r--r--ext/repo_helix.c300
-rw-r--r--ext/repo_mdk.c158
-rw-r--r--ext/repo_products.c265
-rw-r--r--ext/repo_pubkey.c2
-rw-r--r--ext/repo_repomdxml.c220
-rw-r--r--ext/repo_rpmdb.c59
-rw-r--r--ext/repo_rpmmd.c489
-rw-r--r--ext/repo_susetags.c174
-rw-r--r--ext/repo_updateinfoxml.c291
-rw-r--r--ext/repo_zyppdb.c234
-rw-r--r--ext/repodata_diskusage.c78
-rw-r--r--ext/repodata_diskusage.h10
-rw-r--r--ext/solv_xfopen.c47
-rw-r--r--ext/solv_xmlparser.c321
-rw-r--r--ext/solv_xmlparser.h52
-rw-r--r--ext/testcase.c66
23 files changed, 1168 insertions, 2347 deletions
diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt
index 586eda8..bdc6ee9 100644
--- a/ext/CMakeLists.txt
+++ b/ext/CMakeLists.txt
@@ -116,6 +116,16 @@ IF (ENABLE_APPDATA)
repo_appdata.h)
ENDIF (ENABLE_APPDATA)
+IF (ENABLE_RPMMD OR ENABLE_SUSEREPO)
+ SET (libsolvext_SRCS ${libsolvext_SRCS}
+ repodata_diskusage.c)
+ENDIF (ENABLE_RPMMD OR ENABLE_SUSEREPO)
+
+IF (ENABLE_RPMMD OR ENABLE_SUSEREPO OR ENABLE_APPDATA OR ENABLE_COMPS OR ENABLE_HELIXREPO OR ENABLE_MDKREPO)
+ SET (libsolvext_SRCS ${libsolvext_SRCS}
+ solv_xmlparser.c)
+ENDIF (ENABLE_RPMMD OR ENABLE_SUSEREPO OR ENABLE_APPDATA OR ENABLE_COMPS OR ENABLE_HELIXREPO OR ENABLE_MDKREPO)
+
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
IF (HAVE_LINKER_VERSION_SCRIPT)
SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINK_FLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/ext/libsolvext.ver")
diff --git a/ext/pool_fileconflicts.c b/ext/pool_fileconflicts.c
index 6c9119f..cb55d58 100644
--- a/ext/pool_fileconflicts.c
+++ b/ext/pool_fileconflicts.c
@@ -7,8 +7,6 @@
#include <stdio.h>
#include <sys/stat.h>
-#include <sys/stat.h>
-#include <fcntl.h>
#include <unistd.h>
#include "pool.h"
diff --git a/ext/repo_appdata.c b/ext/repo_appdata.c
index 2b9844e..62faf2d 100644
--- a/ext/repo_appdata.c
+++ b/ext/repo_appdata.c
@@ -14,20 +14,17 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <dirent.h>
-#include <expat.h>
#include <errno.h>
#include "pool.h"
#include "repo.h"
#include "util.h"
+#include "solv_xmlparser.h"
#include "repo_appdata.h"
@@ -53,15 +50,8 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-/* !! must be sorted by first column !! */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
{ STATE_START, "applications", STATE_START, 0 },
{ STATE_START, "components", STATE_START, 0 },
{ STATE_START, "application", STATE_APPLICATION, 0 },
@@ -86,23 +76,15 @@ static struct stateswitch stateswitches[] = {
};
struct parsedata {
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
Pool *pool;
Repo *repo;
Repodata *data;
-
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
+ int ret;
Solvable *solvable;
Id handle;
+ int skiplang;
char *description;
int licnt;
int skip_depth;
@@ -111,74 +93,30 @@ struct parsedata {
int havesummary;
const char *filename;
Queue *owners;
-};
-
-static inline const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- if (!strcmp(*atts, txt))
- return atts[1];
- return 0;
-}
+ struct solv_xmlparser xmlp;
+};
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
- struct stateswitch *sw;
const char *type;
-#if 0
- fprintf(stderr, "start: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
-
- pd->depth++;
- if (!pd->swtab[pd->state]) /* no statetable -> no substates */
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */
- if (!strcmp(sw->ename, name))
- break;
-
- if (sw->from != pd->state)
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
-
- if (!pd->skip_depth && find_attr("xml:lang", atts))
- pd->skip_depth = pd->depth;
- if (pd->skip_depth)
+ /* ignore all language tags */
+ if (pd->skiplang || solv_xmlparser_find_attr("xml:lang", atts))
{
- pd->docontent = 0;
+ pd->skiplang++;
return;
}
- switch(pd->state)
+ switch(state)
{
case STATE_APPLICATION:
- type = find_attr("type", atts);
+ type = solv_xmlparser_find_attr("type", atts);
if (!type || !*type)
type = "desktop";
if (strcmp(type, "desktop") != 0)
@@ -206,51 +144,55 @@ startElement(void *userData, const char *name, const char **atts)
/* replace whitespace with one space/newline */
/* also strip starting/ending whitespace */
-static void
+static char *
wsstrip(struct parsedata *pd)
{
+ struct solv_xmlparser *xmlp = &pd->xmlp;
int i, j;
int ws = 0;
- for (i = j = 0; pd->content[i]; i++)
+ for (i = j = 0; xmlp->content[i]; i++)
{
- if (pd->content[i] == ' ' || pd->content[i] == '\t' || pd->content[i] == '\n')
+ if (xmlp->content[i] == ' ' || xmlp->content[i] == '\t' || xmlp->content[i] == '\n')
{
- ws |= pd->content[i] == '\n' ? 2 : 1;
+ ws |= xmlp->content[i] == '\n' ? 2 : 1;
continue;
}
if (ws && j)
- pd->content[j++] = (ws & 2) ? '\n' : ' ';
+ xmlp->content[j++] = (ws & 2) ? '\n' : ' ';
ws = 0;
- pd->content[j++] = pd->content[i];
+ xmlp->content[j++] = xmlp->content[i];
}
- pd->content[j] = 0;
- pd->lcontent = j;
+ xmlp->content[j] = 0;
+ xmlp->lcontent = j;
+ return xmlp->content;
}
/* indent all lines */
-static void
+static char *
indent(struct parsedata *pd, int il)
{
+ struct solv_xmlparser *xmlp = &pd->xmlp;
int i, l;
- for (l = 0; pd->content[l]; )
+ for (l = 0; xmlp->content[l]; )
{
- if (pd->content[l] == '\n')
+ if (xmlp->content[l] == '\n')
{
l++;
continue;
}
- if (pd->lcontent + il + 1 > pd->acontent)
+ if (xmlp->lcontent + il + 1 > xmlp->acontent)
{
- pd->acontent = pd->lcontent + il + 256;
- pd->content = realloc(pd->content, pd->acontent);
+ xmlp->acontent = xmlp->lcontent + il + 256;
+ xmlp->content = realloc(xmlp->content, xmlp->acontent);
}
- memmove(pd->content + l + il, pd->content + l, pd->lcontent - l + 1);
+ memmove(xmlp->content + l + il, xmlp->content + l, xmlp->lcontent - l + 1);
for (i = 0; i < il; i++)
- pd->content[l + i] = ' ';
- pd->lcontent += il;
- while (pd->content[l] && pd->content[l] != '\n')
+ xmlp->content[l + i] = ' ';
+ xmlp->lcontent += il;
+ while (xmlp->content[l] && xmlp->content[l] != '\n')
l++;
}
+ return xmlp->content;
}
static void
@@ -346,47 +288,23 @@ guess_filename_from_id(Pool *pool, const char *id)
return r;
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
Id id;
-#if 0
- fprintf(stderr, "end: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
-#if 0
- fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-#endif
- return;
- }
-
- pd->depth--;
- pd->statedepth--;
-
- if (pd->skip_depth && pd->depth + 1 >= pd->skip_depth)
+ if (pd->skiplang)
{
- if (pd->depth + 1 == pd->skip_depth)
- pd->skip_depth = 0;
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
+ pd->skiplang--;
return;
}
- pd->skip_depth = 0;
-
if (!s)
- {
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
- return;
- }
+ return;
- switch (pd->state)
+ switch (state)
{
case STATE_APPLICATION:
if (!s->arch)
@@ -434,26 +352,26 @@ endElement(void *userData, const char *name)
pd->desktop_file = solv_free(pd->desktop_file);
break;
case STATE_ID:
- pd->desktop_file = solv_strdup(pd->content);
+ pd->desktop_file = solv_strdup(content);
break;
case STATE_NAME:
- s->name = pool_str2id(pd->pool, pool_tmpjoin(pool, "application:", pd->content, 0), 1);
+ s->name = pool_str2id(pd->pool, pool_tmpjoin(pool, "application:", content, 0), 1);
break;
case STATE_LICENCE:
- repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_LICENSE, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_LICENSE, content);
break;
case STATE_SUMMARY:
pd->havesummary = 1;
- repodata_set_str(pd->data, pd->handle, SOLVABLE_SUMMARY, pd->content);
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_SUMMARY, content);
break;
case STATE_URL:
- repodata_set_str(pd->data, pd->handle, SOLVABLE_URL, pd->content);
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_URL, content);
break;
case STATE_GROUP:
- repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_GROUP, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_GROUP, content);
break;
case STATE_EXTENDS:
- repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_EXTENDS, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_EXTENDS, content);
break;
case STATE_DESCRIPTION:
if (pd->description)
@@ -466,83 +384,60 @@ endElement(void *userData, const char *name)
}
break;
case STATE_P:
- wsstrip(pd);
- pd->description = solv_dupappend(pd->description, pd->content, "\n\n");
+ content = wsstrip(pd);
+ pd->description = solv_dupappend(pd->description, content, "\n\n");
break;
case STATE_UL_LI:
wsstrip(pd);
- indent(pd, 4);
- pd->content[2] = '-';
- pd->description = solv_dupappend(pd->description, pd->content, "\n");
+ content = indent(pd, 4);
+ content[2] = '-';
+ pd->description = solv_dupappend(pd->description, content, "\n");
break;
case STATE_OL_LI:
wsstrip(pd);
- indent(pd, 4);
+ content = indent(pd, 4);
if (++pd->licnt >= 10)
- pd->content[0] = '0' + (pd->licnt / 10) % 10;
- pd->content[1] = '0' + pd->licnt % 10;
- pd->content[2] = '.';
- pd->description = solv_dupappend(pd->description, pd->content, "\n");
+ content[0] = '0' + (pd->licnt / 10) % 10;
+ content[1] = '0' + pd->licnt % 10;
+ content[2] = '.';
+ pd->description = solv_dupappend(pd->description, content, "\n");
break;
case STATE_UL:
case STATE_OL:
pd->description = solv_dupappend(pd->description, "\n", 0);
break;
case STATE_PKGNAME:
- id = pool_str2id(pd->pool, pd->content, 1);
+ id = pool_str2id(pd->pool, content, 1);
s->requires = repo_addid_dep(pd->repo, s->requires, id, 0);
- id = pool_str2id(pd->pool, pool_tmpjoin(pd->pool, "application-appdata(", pd->content, ")"), 1);
+ id = pool_str2id(pd->pool, pool_tmpjoin(pd->pool, "application-appdata(", content, ")"), 1);
s->provides = repo_addid_dep(pd->repo, s->provides, id, 0);
break;
case STATE_KEYWORD:
- repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_KEYWORDS, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_KEYWORDS, content);
break;
default:
break;
}
-
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
-
-#if 0
- fprintf(stderr, "end: [%s] -> %d\n", name, pd->state);
-#endif
}
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+static void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- struct parsedata *pd = userData;
- int l;
- char *c;
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->acontent = l + 256;
- pd->content = realloc(pd->content, pd->acontent);
+ struct parsedata *pd = xmlp->userdata;
+ pool_debug(pd->pool, SOLV_ERROR, "repo_appdata: %s at line %u:%u\n", errstr, line, column);
+ pd->ret = -1;
+ if (pd->solvable)
+ {
+ repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1);
+ pd->solvable = 0;
}
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
}
-#define BUFF_SIZE 8192
-
static int
repo_add_appdata_fn(Repo *repo, FILE *fp, int flags, const char *filename, Queue *owners)
{
- Pool *pool = repo->pool;
- struct parsedata pd;
- struct stateswitch *sw;
Repodata *data;
- char buf[BUFF_SIZE];
- int i, l;
- int ret = 0;
+ struct parsedata pd;
data = repo_add_repodata(repo, flags);
memset(&pd, 0, sizeof(pd));
@@ -553,47 +448,17 @@ repo_add_appdata_fn(Repo *repo, FILE *fp, int flags, const char *filename, Queue
pd.filename = filename;
pd.owners = owners;
- pd.content = malloc(256);
- pd.acontent = 256;
-
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
-
- XML_Parser parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd);
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pool_error(pool, -1, "repo_appdata: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- if (pd.solvable)
- {
- repo_free_solvable(repo, pd.solvable - pd.pool->solvables, 1);
- pd.solvable = 0;
- }
- ret = -1;
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
+ solv_free(pd.desktop_file);
+ solv_free(pd.description);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
- solv_free(pd.content);
- solv_free(pd.desktop_file);
- solv_free(pd.description);
- return ret;
+ return pd.ret;
}
int
diff --git a/ext/repo_comps.c b/ext/repo_comps.c
index 8f364dd..255ecb1 100644
--- a/ext/repo_comps.c
+++ b/ext/repo_comps.c
@@ -12,19 +12,15 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
-#include <dirent.h>
-#include <expat.h>
#include "pool.h"
#include "repo.h"
#include "util.h"
+#include "solv_xmlparser.h"
#define DISABLE_SPLIT
#include "tools_util.h"
#include "repo_comps.h"
@@ -62,15 +58,7 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-/* must be sorted by first column */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
{ STATE_START, "comps", STATE_COMPS, 0 },
{ STATE_COMPS, "group", STATE_GROUP, 0 },
{ STATE_COMPS, "category", STATE_CATEGORY, 0 },
@@ -84,11 +72,11 @@ static struct stateswitch stateswitches[] = {
{ STATE_GROUP, "lang_only", STATE_LANG_ONLY, 1 },
{ STATE_GROUP, "packagelist", STATE_PACKAGELIST, 0 },
{ STATE_PACKAGELIST, "packagereq", STATE_PACKAGEREQ, 1 },
- { STATE_CATEGORY, "id", STATE_CID, 1 },
- { STATE_CATEGORY, "name", STATE_CNAME, 1 },
- { STATE_CATEGORY, "description", STATE_CDESCRIPTION, 1 },
+ { STATE_CATEGORY, "id", STATE_ID, 1 },
+ { STATE_CATEGORY, "name", STATE_NAME, 1 },
+ { STATE_CATEGORY, "description", STATE_DESCRIPTION, 1 },
{ STATE_CATEGORY , "grouplist", STATE_GROUPLIST, 0 },
- { STATE_CATEGORY , "display_order", STATE_CDISPLAY_ORDER, 1 },
+ { STATE_CATEGORY , "display_order", STATE_DISPLAY_ORDER, 1 },
{ STATE_GROUPLIST, "groupid", STATE_GROUPID, 1 },
{ NUMSTATES }
};
@@ -99,16 +87,8 @@ struct parsedata {
Repodata *data;
const char *filename;
const char *basename;
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
-
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
+
+ struct solv_xmlparser xmlp;
struct joindata jd;
const char *tmplang;
@@ -116,100 +96,43 @@ struct parsedata {
Id condreq;
Solvable *solvable;
+ const char *kind;
Id handle;
};
-/*
- * find_attr
- * find value for xml attribute
- * I: txt, name of attribute
- * I: atts, list of key/value attributes
- * O: pointer to value of matching key, or NULL
- *
- */
-
-static inline const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- {
- if (!strcmp(*atts, txt))
- return atts[1];
- }
- return 0;
-}
-
-
-/*
- * XML callback: startElement
- */
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
- struct stateswitch *sw;
-
-#if 0
- fprintf(stderr, "start: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
-
- pd->depth++;
- if (!pd->swtab[pd->state]) /* no statetable -> no substates */
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */
- if (!strcmp(sw->ename, name))
- break;
-
- if (sw->from != pd->state)
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
- switch(pd->state)
+ switch(state)
{
case STATE_GROUP:
case STATE_CATEGORY:
s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
pd->handle = s - pool->solvables;
+ pd->kind = state == STATE_GROUP ? "group" : "category";
break;
case STATE_NAME:
case STATE_CNAME:
case STATE_DESCRIPTION:
case STATE_CDESCRIPTION:
- pd->tmplang = join_dup(&pd->jd, find_attr("xml:lang", atts));
+ pd->tmplang = join_dup(&pd->jd, solv_xmlparser_find_attr("xml:lang", atts));
break;
case STATE_PACKAGEREQ:
{
- const char *type = find_attr("type", atts);
+ const char *type = solv_xmlparser_find_attr("type", atts);
pd->condreq = 0;
pd->reqtype = SOLVABLE_RECOMMENDS;
if (type && !strcmp(type, "conditional"))
{
- const char *requires = find_attr("requires", atts);
+ const char *requires = solv_xmlparser_find_attr("requires", atts);
if (requires && *requires)
pd->condreq = pool_str2id(pool, requires, 1);
}
@@ -226,29 +149,14 @@ startElement(void *userData, const char *name, const char **atts)
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Solvable *s = pd->solvable;
Id id;
-#if 0
- fprintf(stderr, "end: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
-#if 0
- fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-#endif
- return;
- }
-
- pd->depth--;
- pd->statedepth--;
-
- switch (pd->state)
+ switch (state)
{
case STATE_GROUP:
case STATE_CATEGORY:
@@ -262,29 +170,26 @@ endElement(void *userData, const char *name)
break;
case STATE_ID:
- case STATE_CID:
- s->name = pool_str2id(pd->pool, join2(&pd->jd, pd->state == STATE_ID ? "group" : "category", ":", pd->content), 1);
+ s->name = pool_str2id(pd->pool, join2(&pd->jd, pd->kind, ":", content), 1);
break;
case STATE_NAME:
- case STATE_CNAME:
- repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), pd->content);
+ repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), content);
break;
case STATE_DESCRIPTION:
- case STATE_CDESCRIPTION:
- repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), pd->content);
+ repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), content);
break;
case STATE_PACKAGEREQ:
- id = pool_str2id(pd->pool, pd->content, 1);
+ id = pool_str2id(pd->pool, content, 1);
if (pd->condreq)
id = pool_rel2id(pd->pool, id, pd->condreq, REL_COND, 1);
repo_add_idarray(pd->repo, pd->handle, pd->reqtype, id);
break;
case STATE_GROUPID:
- id = pool_str2id(pd->pool, join2(&pd->jd, "group", ":", pd->content), 1);
+ id = pool_str2id(pd->pool, join2(&pd->jd, "group", ":", content), 1);
s->requires = repo_addid_dep(pd->repo, s->requires, id, 0);
break;
@@ -293,63 +198,27 @@ endElement(void *userData, const char *name)
break;
case STATE_DISPLAY_ORDER:
- case STATE_CDISPLAY_ORDER:
- repodata_set_str(pd->data, pd->handle, SOLVABLE_ORDER, pd->content);
- break;
-
- case STATE_DEFAULT:
- break;
-
- case STATE_LANGONLY:
- case STATE_LANG_ONLY:
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_ORDER, content);
break;
default:
break;
}
-
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
-
-#if 0
- fprintf(stderr, "end: [%s] -> %d\n", name, pd->state);
-#endif
}
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+static void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- struct parsedata *pd = userData;
- int l;
- char *c;
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
+ struct parsedata *pd = xmlp->userdata;
+ pool_debug(pd->pool, SOLV_ERROR, "repo_comps: %s at line %u:%u\n", errstr, line, column);
}
-#define BUFF_SIZE 8192
-
int
repo_add_comps(Repo *repo, FILE *fp, int flags)
{
Repodata *data;
struct parsedata pd;
- char buf[BUFF_SIZE];
- int i, l;
- struct stateswitch *sw;
- XML_Parser parser;
data = repo_add_repodata(repo, flags);
@@ -357,35 +226,9 @@ repo_add_comps(Repo *repo, FILE *fp, int flags)
pd.repo = repo;
pd.pool = repo->pool;
pd.data = data;
-
- pd.content = solv_malloc(256);
- pd.acontent = 256;
-
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
-
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd);
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pool_debug(pd.pool, SOLV_ERROR, "%s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
-
- solv_free(pd.content);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
join_freemem(&pd.jd);
if (!(flags & REPO_NO_INTERNALIZE))
diff --git a/ext/repo_content.c b/ext/repo_content.c
index b12c4cd..68af2d5 100644
--- a/ext/repo_content.c
+++ b/ext/repo_content.c
@@ -15,8 +15,6 @@
*/
#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/ext/repo_cudf.c b/ext/repo_cudf.c
index 00a4f87..14ddcc9 100644
--- a/ext/repo_cudf.c
+++ b/ext/repo_cudf.c
@@ -11,7 +11,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <zlib.h>
#include <errno.h>
#include "pool.h"
diff --git a/ext/repo_deltainfoxml.c b/ext/repo_deltainfoxml.c
index 06df1a3..4eb340f 100644
--- a/ext/repo_deltainfoxml.c
+++ b/ext/repo_deltainfoxml.c
@@ -5,20 +5,16 @@
* for further information
*/
-#define DO_ARRAY 1
-
#define _GNU_SOURCE
#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <expat.h>
#include "pool.h"
#include "repo.h"
#include "chksum.h"
+#include "solv_xmlparser.h"
#include "repo_deltainfoxml.h"
/*
@@ -52,15 +48,7 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-/* !! must be sorted by first column !! */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
/* compatibility with old yum-presto */
{ STATE_START, "prestodelta", STATE_START, 0 },
{ STATE_START, "deltainfo", STATE_START, 0 },
@@ -93,19 +81,10 @@ struct deltarpm {
struct parsedata {
int ret;
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
Pool *pool;
Repo *repo;
Repodata *data;
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
struct deltarpm delta;
Id newpkgevr;
Id newpkgname;
@@ -113,22 +92,9 @@ struct parsedata {
Id *handles;
int nhandles;
-};
-/*
- * find attribute
- */
-
-static const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- {
- if (!strcmp(*atts, txt))
- return atts[1];
- }
- return 0;
-}
+ struct solv_xmlparser xmlp;
+};
/*
@@ -139,7 +105,7 @@ static Id
makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
{
const char *e, *v, *r, *v2;
- char *c;
+ char *c, *space;
int l;
e = v = r = 0;
@@ -174,12 +140,7 @@ makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
l += strlen(v);
if (r)
l += strlen(r) + 1;
- if (l > pd->acontent)
- {
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content;
+ c = space = solv_xmlparser_contentspace(&pd->xmlp, l);
if (e)
{
strcpy(c, e);
@@ -198,59 +159,28 @@ makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
c += strlen(c);
}
*c = 0;
- if (!*pd->content)
+ if (!*space)
return 0;
#if 0
- fprintf(stderr, "evr: %s\n", pd->content);
+ fprintf(stderr, "evr: %s\n", space);
#endif
- return pool_str2id(pool, pd->content, 1);
+ return pool_str2id(pool, space, 1);
}
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
- struct stateswitch *sw;
const char *str;
-#if 0
- fprintf(stderr, "start: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
-
- pd->depth++;
- if (!pd->swtab[pd->state])
- return;
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */
- if (!strcmp(sw->ename, name))
- break;
- if (sw->from != pd->state)
+ switch(state)
{
-#if 0
- fprintf(stderr, "into unknown: [%d]%s (from: %d)\n", sw->to, name, sw->from);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
-
- switch(pd->state)
- {
- case STATE_START:
- break;
case STATE_NEWPACKAGE:
- if ((str = find_attr("name", atts)) != 0)
+ if ((str = solv_xmlparser_find_attr("name", atts)) != 0)
pd->newpkgname = pool_str2id(pool, str, 1);
pd->newpkgevr = makeevr_atts(pool, pd, atts);
- if ((str = find_attr("arch", atts)) != 0)
+ if ((str = solv_xmlparser_find_attr("arch", atts)) != 0)
pd->newpkgarch = pool_str2id(pool, str, 1);
break;
@@ -259,62 +189,44 @@ startElement(void *userData, const char *name, const char **atts)
pd->delta.bevr = solv_extend(pd->delta.bevr, pd->delta.nbevr, 1, sizeof(Id), 7);
pd->delta.bevr[pd->delta.nbevr++] = makeevr_atts(pool, pd, atts);
break;
+
case STATE_FILENAME:
- if ((str = find_attr("xml:base", atts)))
+ if ((str = solv_xmlparser_find_attr("xml:base", atts)))
pd->delta.locbase = solv_strdup(str);
break;
+
case STATE_LOCATION:
- pd->delta.location = solv_strdup(find_attr("href", atts));
- if ((str = find_attr("xml:base", atts)))
+ pd->delta.location = solv_strdup(solv_xmlparser_find_attr("href", atts));
+ if ((str = solv_xmlparser_find_attr("xml:base", atts)))
pd->delta.locbase = solv_strdup(str);
break;
- case STATE_SIZE:
- break;
+
case STATE_CHECKSUM:
pd->delta.filechecksum = 0;
pd->delta.filechecksumtype = REPOKEY_TYPE_SHA1;
- if ((str = find_attr("type", atts)) != 0)
+ if ((str = solv_xmlparser_find_attr("type", atts)) != 0)
{
pd->delta.filechecksumtype = solv_chksum_str2type(str);
if (!pd->delta.filechecksumtype)
pool_debug(pool, SOLV_ERROR, "unknown checksum type: '%s'\n", str);
}
break;
- case STATE_SEQUENCE:
- break;
+
default:
break;
}
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
const char *str;
-#if 0
- fprintf(stderr, "end: %s\n", name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
-#if 0
- fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-#endif
- return;
- }
-
- pd->depth--;
- pd->statedepth--;
- switch (pd->state)
+ switch (state)
{
- case STATE_START:
- break;
- case STATE_NEWPACKAGE:
- break;
case STATE_DELTA:
{
/* read all data for a deltarpm. commit into attributes */
@@ -356,16 +268,16 @@ endElement(void *userData, const char *name)
pd->delta.locbase = solv_free(pd->delta.locbase);
break;
case STATE_FILENAME:
- pd->delta.location = solv_strdup(pd->content);
+ pd->delta.location = solv_strdup(content);
break;
case STATE_CHECKSUM:
- pd->delta.filechecksum = solv_strdup(pd->content);
+ pd->delta.filechecksum = solv_strdup(content);
break;
case STATE_SIZE:
- pd->delta.downloadsize = strtoull(pd->content, 0, 10);
+ pd->delta.downloadsize = strtoull(content, 0, 10);
break;
case STATE_SEQUENCE:
- if ((str = pd->content))
+ if ((str = content) != 0)
{
const char *s1, *s2;
s1 = strrchr(str, '-');
@@ -392,80 +304,32 @@ endElement(void *userData, const char *name)
default:
break;
}
-
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
}
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- struct parsedata *pd = userData;
- int l;
- char *c;
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
+ struct parsedata *pd = xmlp->userdata;
+ pd->ret = pool_error(pd->pool, -1, "repo_deltainfoxml: %s at line %u:%u", errstr, line, column);
}
-#define BUFF_SIZE 8192
-
int
repo_add_deltainfoxml(Repo *repo, FILE *fp, int flags)
{
Pool *pool = repo->pool;
- struct parsedata pd;
- char buf[BUFF_SIZE];
- int i, l;
- struct stateswitch *sw;
Repodata *data;
- XML_Parser parser;
+ struct parsedata pd;
+ int i;
data = repo_add_repodata(repo, flags);
memset(&pd, 0, sizeof(pd));
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
pd.pool = pool;
pd.repo = repo;
pd.data = data;
-
- pd.content = solv_malloc(256);
- pd.acontent = 256;
- pd.lcontent = 0;
-
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd);
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pd.ret = pool_error(pool, -1, "repo_updateinfoxml: %s at line %u:%u", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
- solv_free(pd.content);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
/* now commit all handles */
if (!pd.ret)
diff --git a/ext/repo_helix.c b/ext/repo_helix.c
index 6358f72..3c2c6d1 100644
--- a/ext/repo_helix.c
+++ b/ext/repo_helix.c
@@ -21,13 +21,12 @@
*/
#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <expat.h>
+#include "queue.h"
+#include "solv_xmlparser.h"
#include "repo_helix.h"
#include "evr.h"
@@ -75,22 +74,10 @@ enum state {
STATE_PATCH,
STATE_PRODUCT,
- STATE_PEPOCH,
- STATE_PVERSION,
- STATE_PRELEASE,
- STATE_PARCH,
-
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
{ STATE_START, "channel", STATE_CHANNEL, 0 },
{ STATE_CHANNEL, "subchannel", STATE_SUBCHANNEL, 0 },
{ STATE_SUBCHANNEL, "package", STATE_PACKAGE, 0 },
@@ -104,10 +91,10 @@ static struct stateswitch stateswitches[] = {
{ STATE_PACKAGE, "name", STATE_NAME, 1 },
{ STATE_PACKAGE, "vendor", STATE_VENDOR, 1 },
{ STATE_PACKAGE, "buildtime", STATE_BUILDTIME, 1 },
- { STATE_PACKAGE, "epoch", STATE_PEPOCH, 1 },
- { STATE_PACKAGE, "version", STATE_PVERSION, 1 },
- { STATE_PACKAGE, "release", STATE_PRELEASE, 1 },
- { STATE_PACKAGE, "arch", STATE_PARCH, 1 },
+ { STATE_PACKAGE, "epoch", STATE_EPOCH, 1 },
+ { STATE_PACKAGE, "version", STATE_VERSION, 1 },
+ { STATE_PACKAGE, "release", STATE_RELEASE, 1 },
+ { STATE_PACKAGE, "arch", STATE_ARCH, 1 },
{ STATE_PACKAGE, "history", STATE_HISTORY, 0 },
{ STATE_PACKAGE, "provides", STATE_PROVIDES, 0 },
{ STATE_PACKAGE, "requires", STATE_REQUIRES, 0 },
@@ -119,6 +106,7 @@ static struct stateswitch stateswitches[] = {
{ STATE_PACKAGE, "suggests", STATE_SUGGESTS, 0 },
{ STATE_PACKAGE, "enhances", STATE_ENHANCES, 0 },
{ STATE_PACKAGE, "freshens", STATE_FRESHENS, 0 },
+ { STATE_PACKAGE, "deps", STATE_PACKAGE, 0 }, /* ignore deps element */
{ STATE_HISTORY, "update", STATE_UPDATE, 0 },
{ STATE_UPDATE, "epoch", STATE_EPOCH, 1 },
@@ -144,17 +132,8 @@ static struct stateswitch stateswitches[] = {
* parser data
*/
-typedef struct _parsedata {
+struct parsedata {
int ret;
- /* XML parser data */
- int depth;
- enum state state; /* current state */
- int statedepth;
- char *content; /* buffer for content of node */
- int lcontent; /* actual length of current content */
- int acontent; /* actual buffer size */
- int docontent; /* handle content */
-
/* repo data */
Pool *pool; /* current pool */
Repo *repo; /* current repo */
@@ -163,6 +142,7 @@ typedef struct _parsedata {
Offset freshens; /* current freshens vector */
/* package data */
+ int srcpackage; /* is srcpackage element */
int epoch; /* epoch (as offset into evrspace) */
int version; /* version (as offset into evrspace) */
int release; /* release (as offset into evrspace) */
@@ -171,9 +151,8 @@ typedef struct _parsedata {
int levrspace; /* actual evr length */
char *kind;
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
-} Parsedata;
+ struct solv_xmlparser xmlp;
+};
/*------------------------------------------------------------------*/
@@ -182,9 +161,9 @@ typedef struct _parsedata {
/* create Id from epoch:version-release */
static Id
-evr2id(Pool *pool, Parsedata *pd, const char *e, const char *v, const char *r)
+evr2id(Pool *pool, struct parsedata *pd, const char *e, const char *v, const char *r)
{
- char *c;
+ char *c, *space;
int l;
/* treat explitcit 0 as NULL */
@@ -211,15 +190,10 @@ evr2id(Pool *pool, Parsedata *pd, const char *e, const char *v, const char *r)
if (r)
l += strlen(r) + 1; /* -r */
- /* extend content if not sufficient */
- if (l > pd->acontent)
- {
- pd->content = (char *)realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
+ /* get content space */
+ c = space = solv_xmlparser_contentspace(&pd->xmlp, l);
- /* copy e-v-r to content */
- c = pd->content;
+ /* copy e-v-r */
if (e)
{
strcpy(c, e);
@@ -239,13 +213,13 @@ evr2id(Pool *pool, Parsedata *pd, const char *e, const char *v, const char *r)
}
*c = 0;
/* if nothing inserted, return Id 0 */
- if (!*pd->content)
- return ID_NULL;
+ if (!*space)
+ return 0;
#if 0
- fprintf(stderr, "evr: %s\n", pd->content);
+ fprintf(stderr, "evr: %s\n", space);
#endif
/* intern and create */
- return pool_str2id(pool, pd->content, 1);
+ return pool_str2id(pool, space, 1);
}
@@ -255,7 +229,7 @@ evr2id(Pool *pool, Parsedata *pd, const char *e, const char *v, const char *r)
* odd index is value
*/
static Id
-evr_atts2id(Pool *pool, Parsedata *pd, const char **atts)
+evr_atts2id(Pool *pool, struct parsedata *pd, const char **atts)
{
const char *e, *v, *r;
e = v = r = 0;
@@ -312,7 +286,7 @@ static struct flagtab flagtab[] = {
*/
static unsigned int
-adddep(Pool *pool, Parsedata *pd, unsigned int olddeps, const char **atts, Id marker)
+adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts, Id marker)
{
Id id, name;
const char *n, *f, *k;
@@ -342,13 +316,9 @@ adddep(Pool *pool, Parsedata *pd, unsigned int olddeps, const char **atts, Id ma
if (k) /* if kind!=package, intern <kind>:<name> */
{
int l = strlen(k) + 1 + strlen(n) + 1;
- if (l > pd->acontent) /* extend buffer if needed */
- {
- pd->content = (char *)realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- sprintf(pd->content, "%s:%s", k, n);
- name = pool_str2id(pool, pd->content, 1);
+ char *space = solv_xmlparser_contentspace(&pd->xmlp, l);
+ sprintf(space, "%s:%s", k, n);
+ name = pool_str2id(pool, space, 1);
}
else
{
@@ -382,76 +352,30 @@ adddep(Pool *pool, Parsedata *pd, unsigned int olddeps, const char **atts, Id ma
/*----------------------------------------------------------------*/
-/*
- * XML callback
- * <name>
- *
- */
-
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- Parsedata *pd = (Parsedata *)userData;
- struct stateswitch *sw;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
-
- /* ignore deps element */
- if (pd->state == STATE_PACKAGE && !strcmp(name, "deps"))
- return;
-
- pd->depth++;
-
- /* find node name in stateswitch */
- if (!pd->swtab[pd->state])
- return;
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)
- {
- if (!strcmp(sw->ename, name))
- break;
- }
-
- /* check if we're at the right level */
- if (sw->from != pd->state)
- {
-#if 0
- fprintf(stderr, "into unknown: %s\n", name);
-#endif
- return;
- }
-
- /* set new state */
- pd->state = sw->to;
-
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
-
- /* start with empty content */
- /* (will collect data until end element) */
- pd->lcontent = 0;
- *pd->content = 0;
-
- switch (pd->state)
+ switch (state)
{
case STATE_NAME:
if (pd->kind) /* if kind is set (non package) */
{
- strcpy(pd->content, pd->kind);
- pd->lcontent = strlen(pd->content);
- pd->content[pd->lcontent++] = ':'; /* prefix name with '<kind>:' */
- pd->content[pd->lcontent] = 0;
+ strcpy(xmlp->content, pd->kind);
+ xmlp->lcontent = strlen(xmlp->content);
+ xmlp->content[xmlp->lcontent++] = ':'; /* prefix name with '<kind>:' */
+ xmlp->content[xmlp->lcontent] = 0;
}
break;
case STATE_PACKAGE: /* solvable name */
pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
+ pd->srcpackage = 0;
+ pd->kind = NULL; /* default is (src)package */
if (!strcmp(name, "selection"))
pd->kind = "selection";
else if (!strcmp(name, "pattern"))
@@ -464,8 +388,8 @@ startElement(void *userData, const char *name, const char **atts)
pd->kind = "patch";
else if (!strcmp(name, "application"))
pd->kind = "application";
- else
- pd->kind = NULL; /* default is package */
+ else if (!strcmp(name, "srcpackage"))
+ pd->srcpackage = 1;
pd->levrspace = 1;
pd->epoch = 0;
pd->version = 0;
@@ -542,7 +466,8 @@ startElement(void *userData, const char *name, const char **atts)
}
}
-static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
+static const char *
+findKernelFlavor(struct parsedata *pd, Solvable *s)
{
Pool *pool = pd->pool;
Id pid, *pidp;
@@ -589,41 +514,21 @@ static const char *findKernelFlavor(Parsedata *pd, Solvable *s)
}
-/*
- * XML callback
- * </name>
- *
- * create Solvable from collected data
- */
-
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- Parsedata *pd = (Parsedata *)userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
Id evr;
unsigned int t = 0;
const char *flavor;
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
- /* printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); */
- return;
- }
-
- /* ignore deps element */
- if (pd->state == STATE_PACKAGE && !strcmp(name, "deps"))
- return;
-
- pd->depth--;
- pd->statedepth--;
- switch (pd->state)
+ switch (state)
{
case STATE_PACKAGE: /* package complete */
- if (name[0] == 's' && name[1] == 'r' && name[2] == 'c' && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+ if (pd->srcpackage && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
s->arch = ARCH_SRC;
if (!s->arch) /* default to "noarch" */
s->arch = ARCH_NOARCH;
@@ -720,13 +625,13 @@ endElement(void *userData, const char *name)
}
break;
case STATE_NAME:
- s->name = pool_str2id(pool, pd->content, 1);
+ s->name = pool_str2id(pool, content, 1);
break;
case STATE_VENDOR:
- s->vendor = pool_str2id(pool, pd->content, 1);
+ s->vendor = pool_str2id(pool, content, 1);
break;
case STATE_BUILDTIME:
- t = atoi (pd->content);
+ t = atoi(content);
if (t)
repodata_set_num(pd->data, s - pool->solvables, SOLVABLE_BUILDTIME, t);
break;
@@ -746,72 +651,38 @@ endElement(void *userData, const char *name)
case STATE_EPOCH:
case STATE_VERSION:
case STATE_RELEASE:
- case STATE_PEPOCH:
- case STATE_PVERSION:
- case STATE_PRELEASE:
/* ensure buffer space */
- if (pd->lcontent + 1 + pd->levrspace > pd->aevrspace)
+ if (xmlp->lcontent + 1 + pd->levrspace > pd->aevrspace)
{
- pd->evrspace = (char *)realloc(pd->evrspace, pd->lcontent + 1 + pd->levrspace + 256);
- pd->aevrspace = pd->lcontent + 1 + pd->levrspace + 256;
+ pd->aevrspace = xmlp->lcontent + 1 + pd->levrspace + 256;
+ pd->evrspace = (char *)realloc(pd->evrspace, pd->aevrspace);
}
- memcpy(pd->evrspace + pd->levrspace, pd->content, pd->lcontent + 1);
- if (pd->state == STATE_EPOCH || pd->state == STATE_PEPOCH)
+ memcpy(pd->evrspace + pd->levrspace, xmlp->content, xmlp->lcontent + 1);
+ if (state == STATE_EPOCH)
pd->epoch = pd->levrspace;
- else if (pd->state == STATE_VERSION || pd->state == STATE_PVERSION)
+ else if (state == STATE_VERSION)
pd->version = pd->levrspace;
else
pd->release = pd->levrspace;
- pd->levrspace += pd->lcontent + 1;
+ pd->levrspace += xmlp->lcontent + 1;
break;
case STATE_ARCH:
- case STATE_PARCH:
- s->arch = pool_str2id(pool, pd->content, 1);
+ s->arch = pool_str2id(pool, content, 1);
break;
default:
break;
}
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
- /* printf("back from known %d %d %d\n", pd->state, pd->depth, pd->statedepth); */
}
-
-/*
- * XML callback
- * character data
- *
- */
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+static void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- Parsedata *pd = (Parsedata *)userData;
- int l;
- char *c;
-
- /* check if current nodes content is interesting */
- if (!pd->docontent)
- return;
-
- /* adapt content buffer */
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = (char *)realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- /* append new content to buffer */
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
+ struct parsedata *pd = xmlp->userdata;
+ pd->ret = pool_error(pd->pool, -1, "%s at line %u", errstr, line);
}
-/*-------------------------------------------------------------------*/
-#define BUFF_SIZE 8192
+/*-------------------------------------------------------------------*/
/*
* read 'helix' type xml from fp
@@ -823,60 +694,29 @@ int
repo_add_helix(Repo *repo, FILE *fp, int flags)
{
Pool *pool = repo->pool;
- Parsedata pd;
+ struct parsedata pd;
Repodata *data;
- char buf[BUFF_SIZE];
- int i, l;
- struct stateswitch *sw;
unsigned int now;
- XML_Parser parser;
now = solv_timems(0);
data = repo_add_repodata(repo, flags);
/* prepare parsedata */
memset(&pd, 0, sizeof(pd));
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
-
pd.pool = pool;
pd.repo = repo;
-
- pd.content = (char *)malloc(256); /* must hold all solvable kinds! */
- pd.acontent = 256;
- pd.lcontent = 0;
-
- pd.evrspace = (char *)malloc(256);
- pd.aevrspace= 256;
- pd.levrspace = 1;
pd.data = data;
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
- /* set up XML parser */
+ pd.evrspace = (char *)solv_malloc(256);
+ pd.aevrspace = 256;
+ pd.levrspace = 1;
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd); /* make parserdata available to XML callbacks */
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
- /* read/parse XML file */
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pd.ret = pool_error(pool, -1, "%s at line %u", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser));
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
- free(pd.content);
- free(pd.evrspace);
+ solv_free(pd.evrspace);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
diff --git a/ext/repo_mdk.c b/ext/repo_mdk.c
index 345d416..418bc61 100644
--- a/ext/repo_mdk.c
+++ b/ext/repo_mdk.c
@@ -11,12 +11,12 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <expat.h>
#include "pool.h"
#include "repo.h"
#include "util.h"
#include "chksum.h"
+#include "solv_xmlparser.h"
#include "repo_mdk.h"
static Offset
@@ -246,15 +246,7 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-/* must be sorted by first column */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
{ STATE_START, "media_info", STATE_MEDIA_INFO, 0 },
{ STATE_MEDIA_INFO, "info", STATE_INFO, 1 },
{ STATE_MEDIA_INFO, "files", STATE_FILES, 1 },
@@ -265,31 +257,12 @@ struct parsedata {
Pool *pool;
Repo *repo;
Repodata *data;
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
Solvable *solvable;
Hashtable joinhash;
Hashval joinhashmask;
+ struct solv_xmlparser xmlp;
};
-static inline const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- {
- if (!strcmp(*atts, txt))
- return atts[1];
- }
- return 0;
-}
-
static Hashtable
joinhash_init(Repo *repo, Hashval *hmp)
{
@@ -380,56 +353,37 @@ joinhash_lookup(Repo *repo, Hashtable ht, Hashval hm, const char *fn, const char
return 0;
}
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
- struct stateswitch *sw;
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
- pd->depth++;
- if (!pd->swtab[pd->state])
- return;
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)
- if (!strcmp(sw->ename, name))
- break;
- if (sw->from != pd->state)
- return;
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
- switch (pd->state)
+ switch (state)
{
case STATE_INFO:
{
- const char *fn = find_attr("fn", atts);
- const char *distepoch = find_attr("distepoch", atts);
+ const char *fn = solv_xmlparser_find_attr("fn", atts);
+ const char *distepoch = solv_xmlparser_find_attr("distepoch", atts);
const char *str;
pd->solvable = joinhash_lookup(pd->repo, pd->joinhash, pd->joinhashmask, fn, distepoch);
if (!pd->solvable)
break;
- str = find_attr("url", atts);
+ str = solv_xmlparser_find_attr("url", atts);
if (str && *str)
repodata_set_str(pd->data, pd->solvable - pool->solvables, SOLVABLE_URL, str);
- str = find_attr("license", atts);
+ str = solv_xmlparser_find_attr("license", atts);
if (str && *str)
repodata_set_poolstr(pd->data, pd->solvable - pool->solvables, SOLVABLE_LICENSE, str);
- str = find_attr("sourcerpm", atts);
+ str = solv_xmlparser_find_attr("sourcerpm", atts);
if (str && *str)
repodata_set_sourcepkg(pd->data, pd->solvable - pool->solvables, str);
break;
}
case STATE_FILES:
{
- const char *fn = find_attr("fn", atts);
- const char *distepoch = find_attr("distepoch", atts);
+ const char *fn = solv_xmlparser_find_attr("fn", atts);
+ const char *distepoch = solv_xmlparser_find_attr("distepoch", atts);
pd->solvable = joinhash_lookup(pd->repo, pd->joinhash, pd->joinhashmask, fn, distepoch);
break;
}
@@ -438,29 +392,22 @@ startElement(void *userData, const char *name, const char **atts)
}
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Solvable *s = pd->solvable;
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
- return;
- }
- pd->depth--;
- pd->statedepth--;
- switch (pd->state)
+ switch (state)
{
case STATE_INFO:
- if (s && *pd->content)
- repodata_set_str(pd->data, s - pd->pool->solvables, SOLVABLE_DESCRIPTION, pd->content);
+ if (s && *content)
+ repodata_set_str(pd->data, s - pd->pool->solvables, SOLVABLE_DESCRIPTION, content);
break;
case STATE_FILES:
- if (s && *pd->content)
+ if (s && *content)
{
char *np, *p, *sl;
- for (p = pd->content; p && *p; p = np)
+ for (p = content; p && *p; p = np)
{
Id id;
np = strchr(p, '\n');
@@ -488,42 +435,21 @@ endElement(void *userData, const char *name)
default:
break;
}
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
}
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+static void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- struct parsedata *pd = userData;
- int l;
- char *c;
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
+ struct parsedata *pd = xmlp->userdata;
+ pool_debug(pd->pool, SOLV_ERROR, "%s at line %u:%u\n", errstr, line, column);
}
-#define BUFF_SIZE 8192
int
repo_add_mdk_info(Repo *repo, FILE *fp, int flags)
{
Repodata *data;
struct parsedata pd;
- char buf[BUFF_SIZE];
- int i, l;
- struct stateswitch *sw;
- XML_Parser parser;
if (!(flags & REPO_EXTEND_SOLVABLES))
{
@@ -537,36 +463,10 @@ repo_add_mdk_info(Repo *repo, FILE *fp, int flags)
pd.repo = repo;
pd.pool = repo->pool;
pd.data = data;
-
- pd.content = solv_malloc(256);
- pd.acontent = 256;
-
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
pd.joinhash = joinhash_init(repo, &pd.joinhashmask);
-
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
-
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd);
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pool_debug(pd.pool, SOLV_ERROR, "%s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
- solv_free(pd.content);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
solv_free(pd.joinhash);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
diff --git a/ext/repo_products.c b/ext/repo_products.c
index 326f8fd..154a909 100644
--- a/ext/repo_products.c
+++ b/ext/repo_products.c
@@ -18,19 +18,16 @@
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <dirent.h>
-#include <expat.h>
#include "pool.h"
#include "repo.h"
#include "util.h"
+#include "solv_xmlparser.h"
#define DISABLE_SPLIT
#include "tools_util.h"
#include "repo_content.h"
@@ -68,15 +65,7 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-/* !! must be sorted by first column !! */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
{ STATE_START, "product", STATE_PRODUCT, 0 },
{ STATE_PRODUCT, "vendor", STATE_VENDOR, 1 },
{ STATE_PRODUCT, "name", STATE_NAME, 1 },
@@ -107,19 +96,11 @@ static struct stateswitch stateswitches[] = {
struct parsedata {
const char *filename;
const char *basename;
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
Pool *pool;
Repo *repo;
Repodata *data;
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
+ struct solv_xmlparser xmlp;
struct joindata jd;
const char *tmplang;
@@ -139,26 +120,6 @@ struct parsedata {
};
-/*
- * find_attr
- * find value for xml attribute
- * I: txt, name of attribute
- * I: atts, list of key/value attributes
- * O: pointer to value of matching key, or NULL
- *
- */
-
-static inline const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- {
- if (!strcmp(*atts, txt))
- return atts[1];
- }
- return 0;
-}
-
static time_t
datestr2timestamp(const char *date)
{
@@ -183,58 +144,19 @@ datestr2timestamp(const char *date)
return timegm(&tm);
}
-/*
- * XML callback: startElement
- */
-
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
- struct stateswitch *sw;
-
-#if 0
- fprintf(stderr, "start: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
-
- pd->depth++;
- if (!pd->swtab[pd->state]) /* no statetable -> no substates */
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */
- if (!strcmp(sw->ename, name))
- break;
-
- if (sw->from != pd->state)
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
- switch(pd->state)
+ switch(state)
{
case STATE_PRODUCT:
/* parse 'schemeversion' and store in global variable */
{
- const char * scheme = find_attr("schemeversion", atts);
+ const char * scheme = solv_xmlparser_find_attr("schemeversion", atts);
pd->productscheme = (scheme && *scheme) ? atoi(scheme) : -1;
}
if (!s)
@@ -247,14 +169,14 @@ startElement(void *userData, const char *name, const char **atts)
/* <summary lang="xy">... */
case STATE_SUMMARY:
case STATE_DESCRIPTION:
- pd->tmplang = join_dup(&pd->jd, find_attr("lang", atts));
+ pd->tmplang = join_dup(&pd->jd, solv_xmlparser_find_attr("lang", atts));
break;
case STATE_URL:
- pd->urltype = pool_str2id(pd->pool, find_attr("name", atts), 1);
+ pd->urltype = pool_str2id(pd->pool, solv_xmlparser_find_attr("name", atts), 1);
break;
case STATE_REGUPDREPO:
{
- const char *repoid = find_attr("repoid", atts);
+ const char *repoid = solv_xmlparser_find_attr("repoid", atts);
if (repoid && *repoid)
{
Id h = repodata_new_handle(pd->data);
@@ -269,28 +191,13 @@ startElement(void *userData, const char *name, const char **atts)
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Solvable *s = pd->solvable;
-#if 0
- fprintf(stderr, "end: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
-#if 0
- fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-#endif
- return;
- }
-
- pd->depth--;
- pd->statedepth--;
-
- switch (pd->state)
+ switch (state)
{
case STATE_PRODUCT:
/* product done, finish solvable */
@@ -326,144 +233,74 @@ endElement(void *userData, const char *name)
pd->solvable = 0;
break;
case STATE_VENDOR:
- s->vendor = pool_str2id(pd->pool, pd->content, 1);
+ s->vendor = pool_str2id(pd->pool, content, 1);
break;
case STATE_NAME:
- s->name = pool_str2id(pd->pool, join2(&pd->jd, "product", ":", pd->content), 1);
+ s->name = pool_str2id(pd->pool, join2(&pd->jd, "product", ":", content), 1);
break;
case STATE_VERSION:
- pd->tmpvers = solv_strdup(pd->content);
+ pd->tmpvers = solv_strdup(content);
break;
case STATE_RELEASE:
- pd->tmprel = solv_strdup(pd->content);
+ pd->tmprel = solv_strdup(content);
break;
case STATE_ARCH:
- s->arch = pool_str2id(pd->pool, pd->content, 1);
+ s->arch = pool_str2id(pd->pool, content, 1);
break;
case STATE_PRODUCTLINE:
- repodata_set_str(pd->data, pd->handle, PRODUCT_PRODUCTLINE, pd->content);
+ repodata_set_str(pd->data, pd->handle, PRODUCT_PRODUCTLINE, content);
break;
case STATE_UPDATEREPOKEY:
/** obsolete **/
break;
case STATE_SUMMARY:
- repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), pd->content);
+ repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), content);
break;
case STATE_SHORTSUMMARY:
- repodata_set_str(pd->data, pd->handle, PRODUCT_SHORTLABEL, pd->content);
+ repodata_set_str(pd->data, pd->handle, PRODUCT_SHORTLABEL, content);
break;
case STATE_DESCRIPTION:
- repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), pd->content);
+ repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), content);
break;
case STATE_URL:
if (pd->urltype)
{
- repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content);
+ repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, content);
repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, pd->urltype);
}
break;
case STATE_TARGET:
- repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_TARGET, pd->content);
+ repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_TARGET, content);
break;
case STATE_REGRELEASE:
- repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_RELEASE, pd->content);
+ repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_RELEASE, content);
break;
case STATE_REGFLAVOR:
- repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_FLAVOR, pd->content);
+ repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_FLAVOR, content);
break;
case STATE_CPEID:
- if (*pd->content)
- repodata_set_str(pd->data, pd->handle, SOLVABLE_CPEID, pd->content);
+ if (*content)
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_CPEID, content);
break;
case STATE_ENDOFLIFE:
/* FATE#320699: Support tri-state product-endoflife (tag absent, present but nodate(0), present + date) */
- repodata_set_num(pd->data, pd->handle, PRODUCT_ENDOFLIFE, (*pd->content ? datestr2timestamp(pd->content) : 0));
+ repodata_set_num(pd->data, pd->handle, PRODUCT_ENDOFLIFE, (*content ? datestr2timestamp(content) : 0));
break;
default:
break;
}
-
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
-
-#if 0
- fprintf(stderr, "end: [%s] -> %d\n", name, pd->state);
-#endif
}
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
-{
- struct parsedata *pd = userData;
- int l;
- char *c;
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
-}
-
-#define BUFF_SIZE 8192
-
-
-/*
- * add single product to repo
- *
- */
-
static void
-add_code11_product(struct parsedata *pd, FILE *fp)
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- char buf[BUFF_SIZE];
- int l;
- struct stat st;
- XML_Parser parser;
-
- if (!fstat(fileno(fp), &st))
- {
- pd->currentproduct = st.st_ino;
- pd->ctime = (unsigned int)st.st_ctime;
- }
- else
- {
- pd->currentproduct = pd->baseproduct + 1; /* make it != baseproduct if stat fails */
- pool_error(pd->pool, 0, "fstat: %s", strerror(errno));
- pd->ctime = 0;
- }
-
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, pd);
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
-
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pool_debug(pd->pool, SOLV_ERROR, "%s: %s at line %u:%u\n", pd->filename, XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- XML_ParserFree(parser);
- if (pd->solvable)
- {
- repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1);
- pd->solvable = 0;
- }
- return;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
+ struct parsedata *pd = xmlp->userdata;
+ pool_debug(pd->pool, SOLV_ERROR, "%s: %s at line %u:%u\n", pd->filename, errstr, line, column);
+ if (pd->solvable)
+ {
+ repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1);
+ pd->solvable = 0;
+ }
}
@@ -472,9 +309,7 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags)
{
Repodata *data;
struct parsedata pd;
- struct stateswitch *sw;
DIR *dir;
- int i;
data = repo_add_repodata(repo, flags);
@@ -483,15 +318,7 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags)
pd.pool = repo->pool;
pd.data = data;
- pd.content = solv_malloc(256);
- pd.acontent = 256;
-
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
if (flags & REPO_USE_ROOTDIR)
dirpath = pool_prepend_rootdir(repo->pool, dirpath);
@@ -521,14 +348,22 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags)
pool_error(repo->pool, 0, "%s: %s", fullpath, strerror(errno));
continue;
}
+ if (fstat(fileno(fp), &st))
+ {
+ pool_error(repo->pool, 0, "%s: %s", fullpath, strerror(errno));
+ fclose(fp);
+ continue;
+ }
+ pd.currentproduct = st.st_ino;
+ pd.ctime = (unsigned int)st.st_ctime;
pd.filename = fullpath;
pd.basename = entry->d_name;
- add_code11_product(&pd, fp);
+ solv_xmlparser_parse(&pd.xmlp, fp);
fclose(fp);
}
closedir(dir);
}
- solv_free(pd.content);
+ solv_xmlparser_free(&pd.xmlp);
join_freemem(&pd.jd);
if (flags & REPO_USE_ROOTDIR)
solv_free((char *)dirpath);
diff --git a/ext/repo_pubkey.c b/ext/repo_pubkey.c
index d8496dc..eb83839 100644
--- a/ext/repo_pubkey.c
+++ b/ext/repo_pubkey.c
@@ -14,8 +14,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/ext/repo_repomdxml.c b/ext/repo_repomdxml.c
index 1d1197e..760d481 100644
--- a/ext/repo_repomdxml.c
+++ b/ext/repo_repomdxml.c
@@ -5,20 +5,16 @@
* for further information
*/
-#define DO_ARRAY 1
-
#define _GNU_SOURCE
#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <expat.h>
#include "pool.h"
#include "repo.h"
#include "chksum.h"
+#include "solv_xmlparser.h"
#include "repo_repomdxml.h"
/*
@@ -110,15 +106,7 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-/* !! must be sorted by first column !! */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
/* suseinfo tags */
{ STATE_START, "repomd", STATE_REPOMD, 0 },
{ STATE_START, "suseinfo", STATE_SUSEINFO, 0 },
@@ -153,20 +141,12 @@ static struct stateswitch stateswitches[] = {
struct parsedata {
int ret;
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
Pool *pool;
Repo *repo;
Repodata *data;
- XML_Parser *parser;
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
+ struct solv_xmlparser xmlp;
+
int timestamp;
/* handles for collection
structures */
@@ -180,66 +160,20 @@ struct parsedata {
Id chksumtype;
};
-/*
- * find attribute
- */
-
-static inline const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- {
- if (!strcmp(*atts, txt))
- return atts[1];
- }
- return 0;
-}
-
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
- /*Pool *pool = pd->pool;*/
- struct stateswitch *sw;
-
-#if 0
- fprintf(stderr, "start: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
+ struct parsedata *pd = xmlp->userdata;
- pd->depth++;
- if (!pd->swtab[pd->state])
- return;
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */
- if (!strcmp(sw->ename, name))
- break;
-
- if (sw->from != pd->state)
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
-
- switch(pd->state)
+ switch(state)
{
case STATE_REPOMD:
{
const char *updstr;
/* this should be OBSOLETE soon */
- updstr = find_attr("updates", atts);
+ updstr = solv_xmlparser_find_attr("updates", atts);
if (updstr)
{
char *value = solv_strdup(updstr);
@@ -253,7 +187,7 @@ startElement(void *userData, const char *name, const char **atts)
repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_UPDATES, value);
value = p;
}
- free(fvalue);
+ solv_free(fvalue);
}
break;
}
@@ -261,7 +195,7 @@ startElement(void *userData, const char *name, const char **atts)
{
/* this is extra metadata about the product this repository
was designed for */
- const char *cpeid = find_attr("cpeid", atts);
+ const char *cpeid = solv_xmlparser_find_attr("cpeid", atts);
pd->rphandle = repodata_new_handle(pd->data);
/* set the cpeid for the product
the label is set in the content of the tag */
@@ -273,7 +207,7 @@ startElement(void *userData, const char *name, const char **atts)
{
/* this is extra metadata about the product this repository
was designed for */
- const char *cpeid = find_attr("cpeid", atts);
+ const char *cpeid = solv_xmlparser_find_attr("cpeid", atts);
pd->ruhandle = repodata_new_handle(pd->data);
/* set the cpeid for the product
the label is set in the content of the tag */
@@ -283,7 +217,7 @@ startElement(void *userData, const char *name, const char **atts)
}
case STATE_DATA:
{
- const char *type= find_attr("type", atts);
+ const char *type= solv_xmlparser_find_attr("type", atts);
pd->rdhandle = repodata_new_handle(pd->data);
if (type)
repodata_set_poolstr(pd->data, pd->rdhandle, REPOSITORY_REPOMD_TYPE, type);
@@ -291,7 +225,7 @@ startElement(void *userData, const char *name, const char **atts)
}
case STATE_LOCATION:
{
- const char *href = find_attr("href", atts);
+ const char *href = solv_xmlparser_find_attr("href", atts);
if (href)
repodata_set_str(pd->data, pd->rdhandle, REPOSITORY_REPOMD_LOCATION, href);
break;
@@ -299,10 +233,10 @@ startElement(void *userData, const char *name, const char **atts)
case STATE_CHECKSUM:
case STATE_OPENCHECKSUM:
{
- const char *type= find_attr("type", atts);
+ const char *type= solv_xmlparser_find_attr("type", atts);
pd->chksumtype = type && *type ? solv_chksum_str2type(type) : 0;
if (!pd->chksumtype)
- pd->ret = pool_error(pd->pool, -1, "line %d: unknown checksum type: %s", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), type ? type : "NULL");
+ pd->ret = pool_error(pd->pool, -1, "line %d: unknown checksum type: %s", solv_xmlparser_lineno(xmlp), type ? type : "NULL");
break;
}
default:
@@ -311,27 +245,11 @@ startElement(void *userData, const char *name, const char **atts)
return;
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
- /* Pool *pool = pd->pool; */
-
-#if 0
- fprintf(stderr, "endElement: %s\n", name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
-#if 0
- fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-#endif
- return;
- }
-
- pd->depth--;
- pd->statedepth--;
- switch (pd->state)
+ struct parsedata *pd = xmlp->userdata;
+ switch (state)
{
case STATE_REPOMD:
if (pd->timestamp > 0)
@@ -347,10 +265,10 @@ endElement(void *userData, const char *name)
case STATE_OPENCHECKSUM:
if (!pd->chksumtype)
break;
- if (strlen(pd->content) != 2 * solv_chksum_len(pd->chksumtype))
- pd->ret = pool_error(pd->pool, -1, "line %d: invalid checksum length for %s", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), solv_chksum_type2str(pd->chksumtype));
+ if (strlen(content) != 2 * solv_chksum_len(pd->chksumtype))
+ pd->ret = pool_error(pd->pool, -1, "line %d: invalid checksum length for %s", solv_xmlparser_lineno(xmlp), solv_chksum_type2str(pd->chksumtype));
else
- repodata_set_checksum(pd->data, pd->rdhandle, pd->state == STATE_CHECKSUM ? REPOSITORY_REPOMD_CHECKSUM : REPOSITORY_REPOMD_OPENCHECKSUM, pd->chksumtype, pd->content);
+ repodata_set_checksum(pd->data, pd->rdhandle, state == STATE_CHECKSUM ? REPOSITORY_REPOMD_CHECKSUM : REPOSITORY_REPOMD_OPENCHECKSUM, pd->chksumtype, content);
break;
case STATE_TIMESTAMP:
@@ -360,7 +278,7 @@ endElement(void *userData, const char *name)
* of all resources to save it as the time
* the metadata was generated
*/
- int timestamp = atoi(pd->content);
+ int timestamp = atoi(content);
if (timestamp)
repodata_set_num(pd->data, pd->rdhandle, REPOSITORY_REPOMD_TIMESTAMP, timestamp);
if (timestamp > pd->timestamp)
@@ -369,7 +287,7 @@ endElement(void *userData, const char *name)
}
case STATE_EXPIRE:
{
- int expire = atoi(pd->content);
+ int expire = atoi(content);
if (expire > 0)
repodata_set_num(pd->data, SOLVID_META, REPOSITORY_EXPIRE, expire);
break;
@@ -377,119 +295,69 @@ endElement(void *userData, const char *name)
/* repomd.xml content and suseinfo.xml keywords are equivalent */
case STATE_CONTENT:
case STATE_KEYWORD:
- if (*pd->content)
- repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_KEYWORDS, pd->content);
+ if (*content)
+ repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_KEYWORDS, content);
break;
case STATE_REVISION:
- if (*pd->content)
- repodata_set_str(pd->data, SOLVID_META, REPOSITORY_REVISION, pd->content);
+ if (*content)
+ repodata_set_str(pd->data, SOLVID_META, REPOSITORY_REVISION, content);
break;
case STATE_DISTRO:
/* distro tag is used in repomd.xml to say the product this repo is
made for */
- if (*pd->content)
- repodata_set_str(pd->data, pd->rphandle, REPOSITORY_PRODUCT_LABEL, pd->content);
+ if (*content)
+ repodata_set_str(pd->data, pd->rphandle, REPOSITORY_PRODUCT_LABEL, content);
repodata_add_flexarray(pd->data, SOLVID_META, REPOSITORY_DISTROS, pd->rphandle);
break;
case STATE_UPDATES:
/* updates tag is used in suseinfo.xml to say the repo updates a product
however it s not yet a tag standarized for repomd.xml */
- if (*pd->content)
- repodata_set_str(pd->data, pd->ruhandle, REPOSITORY_PRODUCT_LABEL, pd->content);
+ if (*content)
+ repodata_set_str(pd->data, pd->ruhandle, REPOSITORY_PRODUCT_LABEL, content);
repodata_add_flexarray(pd->data, SOLVID_META, REPOSITORY_UPDATES, pd->ruhandle);
break;
case STATE_REPO:
- if (*pd->content)
- repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_REPOID, pd->content);
+ if (*content)
+ repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_REPOID, content);
break;
case STATE_SIZE:
- if (*pd->content)
- repodata_set_num(pd->data, pd->rdhandle, REPOSITORY_REPOMD_SIZE, strtoull(pd->content, 0, 10));
+ if (*content)
+ repodata_set_num(pd->data, pd->rdhandle, REPOSITORY_REPOMD_SIZE, strtoull(content, 0, 10));
break;
default:
break;
}
-
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
-
- return;
}
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+static void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- struct parsedata *pd = userData;
- int l;
- char *c;
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
+ struct parsedata *pd = xmlp->userdata;
+ pd->ret = pool_error(pd->pool, -1, "repo_repomdxml: %s at line %u:%u", errstr, line, column);
}
-#define BUFF_SIZE 8192
-
int
repo_add_repomdxml(Repo *repo, FILE *fp, int flags)
{
Pool *pool = repo->pool;
struct parsedata pd;
Repodata *data;
- char buf[BUFF_SIZE];
- int i, l;
- struct stateswitch *sw;
- XML_Parser parser;
data = repo_add_repodata(repo, flags);
memset(&pd, 0, sizeof(pd));
pd.timestamp = 0;
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
pd.pool = pool;
pd.repo = repo;
pd.data = data;
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
- pd.content = malloc(256);
- pd.acontent = 256;
- pd.lcontent = 0;
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd);
- pd.parser = &parser;
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pd.ret = pool_error(pool, -1, "repo_repomdxml: %s at line %u:%u", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
- free(pd.content);
return pd.ret;
}
diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c
index fe05bec..40a1e3e 100644
--- a/ext/repo_rpmdb.c
+++ b/ext/repo_rpmdb.c
@@ -624,6 +624,24 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf,
return olddeps;
}
+static Id
+repodata_str2dir_rooted(Repodata *data, char *str, int create)
+{
+ char buf[256], *bp;
+ int l = strlen(str);
+ Id id;
+
+ if (l + 2 <= sizeof(buf))
+ bp = buf;
+ else
+ bp = solv_malloc(l + 2);
+ bp[0] = '/';
+ strcpy(bp + 1, str);
+ id = repodata_str2dir(data, bp, create);
+ if (bp != buf)
+ solv_free(bp);
+ return id;
+}
static void
adddudata(Repodata *data, Id handle, RpmHead *rpmhead, char **dn, unsigned int *di, int fc, int dc)
@@ -765,15 +783,16 @@ adddudata(Repodata *data, Id handle, RpmHead *rpmhead, char **dn, unsigned int *
{
if (!fn[i])
continue;
- did = repodata_str2dir(data, dn[i], 1);
- if (!did)
+ if (dn[i][0] != '/')
{
Solvable *s = data->repo->pool->solvables + handle;
if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
did = repodata_str2dir(data, "/usr/src", 1);
else
- continue; /* work around rpm bug */
+ did = repodata_str2dir_rooted(data, dn[i], 1);
}
+ else
+ did = repodata_str2dir(data, dn[i], 1);
repodata_add_dirnumnum(data, handle, SOLVABLE_DISKUSAGE, did, fkb[i], fn[i]);
}
solv_free(fn);
@@ -803,7 +822,7 @@ addfilelist(Repodata *data, Id handle, RpmHead *rpmhead, int flags)
unsigned int *di;
int bnc, dnc, dic;
int i;
- Id lastdid = 0;
+ Id did;
unsigned int lastdii = -1;
int lastfiltered = 0;
@@ -833,17 +852,16 @@ addfilelist(Repodata *data, Id handle, RpmHead *rpmhead, int flags)
adddudata(data, handle, rpmhead, dn, di, bnc, dnc);
+ did = -1;
for (i = 0; i < bnc; i++)
{
- Id did;
char *b = bn[i];
- if (lastdid && di[i] == lastdii)
- did = lastdid;
- else
+ if (did < 0 || di[i] != lastdii)
{
if (di[i] >= dnc)
continue; /* corrupt entry */
+ did = 0;
lastdii = di[i];
if ((flags & RPM_ADD_FILTERED_FILELIST) != 0)
{
@@ -851,18 +869,17 @@ addfilelist(Repodata *data, Id handle, RpmHead *rpmhead, int flags)
if (lastfiltered == 1)
continue;
}
- did = repodata_str2dir(data, dn[lastdii], 1);
- if (!did)
- did = repodata_str2dir(data, "/", 1);
- lastdid = did;
+ if (dn[lastdii][0] != '/')
+ did = repodata_str2dir_rooted(data, dn[lastdii], 1);
+ else
+ did = repodata_str2dir(data, dn[lastdii], 1);
}
- if (b && *b == '/') /* work around rpm bug */
+ if (!b)
+ continue;
+ if (*b == '/') /* work around rpm bug */
b++;
- if (lastfiltered)
- {
- if (lastfiltered != 2 || strcmp(b, "sendmail"))
- continue;
- }
+ if (lastfiltered && (lastfiltered != 2 || strcmp(b, "sendmail")))
+ continue;
repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, b);
}
solv_free(bn);
@@ -1652,12 +1669,14 @@ solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, K
case REPOKEY_TYPE_DIRNUMNUMARRAY:
id = kv->id;
id = copydir(pool, data, fromdata, id, cbdata->dircache);
- repodata_add_dirnumnum(data, handle, keyname, id, kv->num, kv->num2);
+ if (id)
+ repodata_add_dirnumnum(data, handle, keyname, id, kv->num, kv->num2);
break;
case REPOKEY_TYPE_DIRSTRARRAY:
id = kv->id;
id = copydir(pool, data, fromdata, id, cbdata->dircache);
- repodata_add_dirstr(data, handle, keyname, id, kv->str);
+ if (id)
+ repodata_add_dirstr(data, handle, keyname, id, kv->str);
break;
case REPOKEY_TYPE_FLEXARRAY:
if (kv->eof == 2)
diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c
index 8854bca..6c05281 100644
--- a/ext/repo_rpmmd.c
+++ b/ext/repo_rpmmd.c
@@ -6,12 +6,9 @@
*/
#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <expat.h>
#include "pool.h"
#include "repo.h"
@@ -19,9 +16,11 @@
#include "tools_util.h"
#include "repo_rpmmd.h"
#include "chksum.h"
+#include "solv_xmlparser.h"
#ifdef ENABLE_COMPLEX_DEPS
#include "pool_parserpmrichdep.h"
#endif
+#include "repodata_diskusage.h"
enum state {
STATE_START,
@@ -85,8 +84,7 @@ enum state {
STATE_OPTIONALURL,
STATE_FLAG,
- /* rpm-md dependencies inside the
- format tag */
+ /* rpm-md dependencies inside the format tag */
STATE_PROVIDES,
STATE_REQUIRES,
STATE_OBSOLETES,
@@ -117,18 +115,13 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-static struct stateswitch stateswitches[] = {
- /** fake tag used to enclose 2 different xml files in one **/
+static struct solv_xmlparser_element stateswitches[] = {
+ /** fake tag used to enclose multiple xml files in one **/
{ STATE_START, "rpmmd", STATE_START, 0 },
- /** tags for different package data, we just ignore the tag **/
+ /** tags for different package data, just ignore them **/
+ { STATE_START, "patterns", STATE_START, 0 },
+ { STATE_START, "products", STATE_START, 0 },
{ STATE_START, "metadata", STATE_START, 0 },
{ STATE_START, "otherdata", STATE_START, 0 },
{ STATE_START, "filelists", STATE_START, 0 },
@@ -140,6 +133,8 @@ static struct stateswitch stateswitches[] = {
{ STATE_START, "patch", STATE_SOLVABLE, 0 },
{ STATE_START, "package", STATE_SOLVABLE, 0 },
+ { STATE_SOLVABLE, "format", STATE_SOLVABLE, 0 },
+
{ STATE_SOLVABLE, "name", STATE_NAME, 1 },
{ STATE_SOLVABLE, "arch", STATE_ARCH, 1 },
{ STATE_SOLVABLE, "version", STATE_VERSION, 0 },
@@ -230,25 +225,16 @@ struct parsedata {
Repo *repo;
Repodata *data;
char *kind;
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
Solvable *solvable;
Offset freshens;
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
+
+ struct solv_xmlparser xmlp;
struct joindata jd;
/* temporal to store attribute tag language */
const char *tmplang;
Id chksumtype;
Id handle;
- XML_Parser *parser;
- Id (*dirs)[3]; /* dirid, size, nfiles */
- int ndirs;
+ Queue diskusageq;
const char *language; /* default language */
Id langcache[ID_NUM_INTERNAL]; /* cache for the default language */
@@ -287,74 +273,6 @@ langtag(struct parsedata *pd, Id tag, const char *language)
return pd->langcache[tag];
}
-static int
-id3_cmp (const void *v1, const void *v2, void *dp)
-{
- Id *i1 = (Id*)v1;
- Id *i2 = (Id*)v2;
- return i1[0] - i2[0];
-}
-
-static void
-commit_diskusage (struct parsedata *pd, Id handle)
-{
- int i;
- Dirpool *dp = &pd->data->dirpool;
- /* Now sort in dirid order. This ensures that parents come before
- their children. */
- if (pd->ndirs > 1)
- solv_sort(pd->dirs, pd->ndirs, sizeof (pd->dirs[0]), id3_cmp, 0);
- /* Substract leaf numbers from all parents to make the numbers
- non-cumulative. This must be done post-order (i.e. all leafs
- adjusted before parents). We ensure this by starting at the end of
- the array moving to the start, hence seeing leafs before parents. */
- for (i = pd->ndirs; i--;)
- {
- Id p = dirpool_parent(dp, pd->dirs[i][0]);
- int j = i;
- for (; p; p = dirpool_parent(dp, p))
- {
- for (; j--;)
- if (pd->dirs[j][0] == p)
- break;
- if (j >= 0)
- {
- if (pd->dirs[j][1] < pd->dirs[i][1])
- pd->dirs[j][1] = 0;
- else
- pd->dirs[j][1] -= pd->dirs[i][1];
- if (pd->dirs[j][2] < pd->dirs[i][2])
- pd->dirs[j][2] = 0;
- else
- pd->dirs[j][2] -= pd->dirs[i][2];
- }
- else
- /* Haven't found this parent in the list, look further if
- we maybe find the parents parent. */
- j = i;
- }
- }
-#if 0
- char sbuf[1024];
- char *buf = sbuf;
- unsigned slen = sizeof (sbuf);
- for (i = 0; i < pd->ndirs; i++)
- {
- dir2str (attr, pd->dirs[i][0], &buf, &slen);
- fprintf (stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
- }
- if (buf != sbuf)
- free (buf);
-#endif
- for (i = 0; i < pd->ndirs; i++)
- if (pd->dirs[i][1] || pd->dirs[i][2])
- {
- repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
- }
- pd->ndirs = 0;
-}
-
-
/*
* makeevr_atts
* parse 'epoch', 'ver' and 'rel', return evr Id
@@ -365,7 +283,7 @@ static Id
makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
{
const char *e, *v, *r, *v2;
- char *c;
+ char *c, *space;
int l;
e = v = r = 0;
@@ -394,12 +312,7 @@ makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
l += strlen(v);
if (r)
l += strlen(r) + 1;
- if (l > pd->acontent)
- {
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content;
+ c = space = solv_xmlparser_contentspace(&pd->xmlp, l);
if (e)
{
strcpy(c, e);
@@ -418,33 +331,12 @@ makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
c += strlen(c);
}
*c = 0;
- if (!*pd->content)
+ if (!*space)
return 0;
#if 0
- fprintf(stderr, "evr: %s\n", pd->content);
+ fprintf(stderr, "evr: %s\n", space);
#endif
- return pool_str2id(pool, pd->content, 1);
-}
-
-
-/*
- * find_attr
- * find value for xml attribute
- * I: txt, name of attribute
- * I: atts, list of key/value attributes
- * O: pointer to value of matching key, or NULL
- *
- */
-
-static inline const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- {
- if (!strcmp(*atts, txt))
- return atts[1];
- }
- return 0;
+ return pool_str2id(pool, space, 1);
}
@@ -495,13 +387,9 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts
if (k)
{
int l = strlen(k) + 1 + strlen(n) + 1;
- if (l > pd->acontent)
- {
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- sprintf(pd->content, "%s:%s", k, n);
- id = pool_str2id(pool, pd->content, 1);
+ char *space = solv_xmlparser_contentspace(&pd->xmlp, l);
+ sprintf(space, "%s:%s", k, n);
+ id = pool_str2id(pool, space, 1);
}
#ifdef ENABLE_COMPLEX_DEPS
else if (!f && n[0] == '(')
@@ -734,63 +622,22 @@ fill_cshash_from_new_solvables(struct parsedata *pd)
/*
* startElement
- * XML callback
- *
*/
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
- struct stateswitch *sw;
- const char *str;
Id handle = pd->handle;
+ const char *str;
const char *pkgid;
- /* fprintf(stderr, "into %s, from %d, depth %d, statedepth %d\n", name, pd->state, pd->depth, pd->statedepth); */
-
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
-
- if (pd->state == STATE_START && !strcmp(name, "patterns"))
- return;
- if (pd->state == STATE_START && !strcmp(name, "products"))
- return;
-#if 0
- if (pd->state == STATE_START && !strcmp(name, "metadata"))
- return;
-#endif
- if (pd->state == STATE_SOLVABLE && !strcmp(name, "format"))
- return;
-
- pd->depth++;
- if (!pd->swtab[pd->state])
+ if (!s && state != STATE_SOLVABLE)
return;
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)
- if (!strcmp(sw->ename, name))
- break;
- if (sw->from != pd->state)
- {
-#if 0
- fprintf(stderr, "into unknown: %s\n", name);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
- if (!s && pd->state != STATE_SOLVABLE)
- return;
-
- switch(pd->state)
+ switch(state)
{
case STATE_SOLVABLE:
pd->kind = 0;
@@ -818,7 +665,7 @@ startElement(void *userData, const char *name, const char **atts)
one.
*/
pd->extending = 0;
- if ((pkgid = find_attr("pkgid", atts)) != NULL)
+ if ((pkgid = solv_xmlparser_find_attr("pkgid", atts)) != NULL)
{
unsigned char chk[256];
int l;
@@ -859,7 +706,7 @@ startElement(void *userData, const char *name, const char **atts)
if (pd->kind && pd->kind[1] == 'r')
{
/* products can have a type */
- const char *type = find_attr("type", atts);
+ const char *type = solv_xmlparser_find_attr("type", atts);
if (type && *type)
repodata_set_str(pd->data, handle, PRODUCT_TYPE, type);
}
@@ -931,27 +778,27 @@ startElement(void *userData, const char *name, const char **atts)
case STATE_SUMMARY:
case STATE_CATEGORY:
case STATE_DESCRIPTION:
- pd->tmplang = join_dup(&pd->jd, find_attr("lang", atts));
+ pd->tmplang = join_dup(&pd->jd, solv_xmlparser_find_attr("lang", atts));
break;
case STATE_USERVISIBLE:
repodata_set_void(pd->data, handle, SOLVABLE_ISVISIBLE);
break;
case STATE_INCLUDESENTRY:
- str = find_attr("pattern", atts);
+ str = solv_xmlparser_find_attr("pattern", atts);
if (str)
repodata_add_poolstr_array(pd->data, handle, SOLVABLE_INCLUDES, join2(&pd->jd, "pattern", ":", str));
break;
case STATE_EXTENDSENTRY:
- str = find_attr("pattern", atts);
+ str = solv_xmlparser_find_attr("pattern", atts);
if (str)
repodata_add_poolstr_array(pd->data, handle, SOLVABLE_EXTENDS, join2(&pd->jd, "pattern", ":", str));
break;
case STATE_LOCATION:
- str = find_attr("href", atts);
+ str = solv_xmlparser_find_attr("href", atts);
if (str)
{
int medianr = 0;
- const char *base = find_attr("xml:base", atts);
+ const char *base = solv_xmlparser_find_attr("xml:base", atts);
if (base && !strncmp(base, "media:", 6))
{
/* check for the media number in the fragment */
@@ -967,29 +814,29 @@ startElement(void *userData, const char *name, const char **atts)
}
break;
case STATE_CHECKSUM:
- str = find_attr("type", atts);
+ str = solv_xmlparser_find_attr("type", atts);
pd->chksumtype = str && *str ? solv_chksum_str2type(str) : 0;
if (!pd->chksumtype)
- pd->ret = pool_error(pool, -1, "line %d: unknown checksum type: %s", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), str ? str : "NULL");
+ pd->ret = pool_error(pool, -1, "line %d: unknown checksum type: %s", solv_xmlparser_lineno(xmlp), str ? str : "NULL");
break;
case STATE_TIME:
{
unsigned int t;
- str = find_attr("build", atts);
+ str = solv_xmlparser_find_attr("build", atts);
if (str && (t = atoi(str)) != 0)
repodata_set_num(pd->data, handle, SOLVABLE_BUILDTIME, t);
break;
}
case STATE_SIZE:
- if ((str = find_attr("installed", atts)) != 0)
+ if ((str = solv_xmlparser_find_attr("installed", atts)) != 0)
repodata_set_num(pd->data, handle, SOLVABLE_INSTALLSIZE, strtoull(str, 0, 10));
- if ((str = find_attr("package", atts)) != 0)
+ if ((str = solv_xmlparser_find_attr("package", atts)) != 0)
repodata_set_num(pd->data, handle, SOLVABLE_DOWNLOADSIZE, strtoull(str, 0, 10));
break;
case STATE_HEADERRANGE:
{
unsigned int end;
- str = find_attr("end", atts);
+ str = solv_xmlparser_find_attr("end", atts);
if (str && (end = atoi(str)) != 0)
repodata_set_num(pd->data, handle, SOLVABLE_HEADEREND, end);
break;
@@ -1013,41 +860,43 @@ startElement(void *userData, const char *name, const char **atts)
case STATE_DIR:
{
long filesz = 0, filenum = 0;
- Id dirid;
- if ((str = find_attr("name", atts)) == 0)
+ Id did;
+
+ if ((str = solv_xmlparser_find_attr("name", atts)) == 0)
{
pd->ret = pool_error(pool, -1, "<dir .../> tag without 'name' attribute");
break;
}
if (*str != '/')
{
- int l = strlen(str) + 2;
- if (l > pd->acontent)
+ if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
+ str = "/usr/src";
+ else
{
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- *pd->content = '/';
- strcpy(pd->content + 1, str);
- str = pd->content;
+ int l = strlen(str) + 2;
+ char *space = solv_xmlparser_contentspace(xmlp, l);
+ space[0] = '/';
+ memcpy(space + 1, str, l - 1);
+ str = space;
+ }
}
- dirid = repodata_str2dir(pd->data, str, 1);
- if ((str = find_attr("size", atts)) != 0)
+ did = repodata_str2dir(pd->data, str, 1);
+ if ((str = solv_xmlparser_find_attr("size", atts)) != 0)
filesz = strtol(str, 0, 0);
- if ((str = find_attr("count", atts)) != 0)
+ if ((str = solv_xmlparser_find_attr("count", atts)) != 0)
filenum = strtol(str, 0, 0);
- pd->dirs = solv_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
- pd->dirs[pd->ndirs][0] = dirid;
- pd->dirs[pd->ndirs][1] = filesz;
- pd->dirs[pd->ndirs][2] = filenum;
- pd->ndirs++;
+ if (filesz || filenum)
+ {
+ queue_push(&pd->diskusageq, did);
+ queue_push2(&pd->diskusageq, filesz, filenum);
+ }
break;
}
case STATE_CHANGELOG:
pd->changelog_handle = repodata_new_handle(pd->data);
- if ((str = find_attr("date", atts)) != 0)
+ if ((str = solv_xmlparser_find_attr("date", atts)) != 0)
repodata_set_num(pd->data, pd->changelog_handle, SOLVABLE_CHANGELOG_TIME, strtoull(str, 0, 10));
- if ((str = find_attr("author", atts)) != 0)
+ if ((str = solv_xmlparser_find_attr("author", atts)) != 0)
repodata_set_str(pd->data, pd->changelog_handle, SOLVABLE_CHANGELOG_AUTHOR, str);
break;
default:
@@ -1058,14 +907,12 @@ startElement(void *userData, const char *name, const char **atts)
/*
* endElement
- * XML callback
- *
*/
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
Repo *repo = pd->repo;
@@ -1073,37 +920,10 @@ endElement(void *userData, const char *name)
Id id;
char *p;
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
- /* printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); */
- return;
- }
-
- /* ignore patterns & metadata */
- if (pd->state == STATE_START && !strcmp(name, "patterns"))
- return;
- if (pd->state == STATE_START && !strcmp(name, "products"))
- return;
-#if 0
- if (pd->state == STATE_START && !strcmp(name, "metadata"))
- return;
-#endif
- if (pd->state == STATE_SOLVABLE && !strcmp(name, "format"))
- return;
-
- pd->depth--;
- pd->statedepth--;
-
-
if (!s)
- {
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
- return;
- }
+ return;
- switch (pd->state)
+ switch (state)
{
case STATE_SOLVABLE:
if (pd->extending)
@@ -1126,32 +946,32 @@ endElement(void *userData, const char *name)
break;
case STATE_NAME:
if (pd->kind)
- s->name = pool_str2id(pool, join2(&pd->jd, pd->kind, ":", pd->content), 1);
+ s->name = pool_str2id(pool, join2(&pd->jd, pd->kind, ":", content), 1);
else
- s->name = pool_str2id(pool, pd->content, 1);
+ s->name = pool_str2id(pool, content, 1);
break;
case STATE_ARCH:
- s->arch = pool_str2id(pool, pd->content, 1);
+ s->arch = pool_str2id(pool, content, 1);
break;
case STATE_VENDOR:
- s->vendor = pool_str2id(pool, pd->content, 1);
+ s->vendor = pool_str2id(pool, content, 1);
break;
case STATE_RPM_GROUP:
- repodata_set_poolstr(pd->data, handle, SOLVABLE_GROUP, pd->content);
+ repodata_set_poolstr(pd->data, handle, SOLVABLE_GROUP, content);
break;
case STATE_RPM_LICENSE:
- repodata_set_poolstr(pd->data, handle, SOLVABLE_LICENSE, pd->content);
+ repodata_set_poolstr(pd->data, handle, SOLVABLE_LICENSE, content);
break;
case STATE_CHECKSUM:
{
unsigned char chk[256];
int l = solv_chksum_len(pd->chksumtype);
- const char *str = pd->content;
+ const char *str = content;
if (!l || l > sizeof(chk))
break;
- if (solv_hex2bin(&str, chk, l) != l || pd->content[2 * l])
+ if (solv_hex2bin(&str, chk, l) != l || content[2 * l])
{
- pd->ret = pool_error(pool, -1, "line %u: invalid %s checksum", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), solv_chksum_type2str(pd->chksumtype));
+ pd->ret = pool_error(pool, -1, "line %u: invalid %s checksum", solv_xmlparser_lineno(xmlp), solv_chksum_type2str(pd->chksumtype));
break;
}
repodata_set_bin_checksum(pd->data, handle, SOLVABLE_CHECKSUM, pd->chksumtype, chk);
@@ -1161,152 +981,124 @@ endElement(void *userData, const char *name)
break;
}
case STATE_FILE:
-#if 0
- id = pool_str2id(pool, pd->content, 1);
- s->provides = repo_addid_dep(repo, s->provides, id, SOLVABLE_FILEMARKER);
-#endif
- if ((p = strrchr(pd->content, '/')) != 0)
+ if ((p = strrchr(content, '/')) != 0)
{
*p++ = 0;
- if (pd->lastdir && !strcmp(pd->lastdirstr, pd->content))
+ if (pd->lastdir && !strcmp(pd->lastdirstr, content))
{
id = pd->lastdir;
}
else
{
- int l;
- id = repodata_str2dir(pd->data, pd->content, 1);
- l = strlen(pd->content) + 1;
- if (l > pd->lastdirstrl)
+ int l = p - content;
+ if (l + 1 > pd->lastdirstrl) /* + 1 for the possible leading / we need to insert */
{
pd->lastdirstrl = l + 128;
pd->lastdirstr = solv_realloc(pd->lastdirstr, pd->lastdirstrl);
}
- strcpy(pd->lastdirstr, pd->content);
+ if (content[0] != '/')
+ {
+ pd->lastdirstr[0] = '/';
+ memcpy(pd->lastdirstr + 1, content, l);
+ id = repodata_str2dir(pd->data, pd->lastdirstr, 1);
+ }
+ else
+ id = repodata_str2dir(pd->data, content, 1);
pd->lastdir = id;
+ memcpy(pd->lastdirstr, content, l);
}
}
else
{
- p = pd->content;
- id = 0;
+ p = content;
+ id = repodata_str2dir(pd->data, "/", 1);
}
- if (!id)
- id = repodata_str2dir(pd->data, "/", 1);
repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, id, p);
break;
case STATE_SUMMARY:
- repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_SUMMARY, pd->tmplang), pd->content);
+ repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_SUMMARY, pd->tmplang), content);
break;
case STATE_DESCRIPTION:
- set_description_author(pd->data, handle, pd->content, pd);
+ set_description_author(pd->data, handle, content, pd);
break;
case STATE_CATEGORY:
- repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_CATEGORY, pd->tmplang), pd->content);
+ repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_CATEGORY, pd->tmplang), content);
break;
case STATE_DISTRIBUTION:
- repodata_set_poolstr(pd->data, handle, SOLVABLE_DISTRIBUTION, pd->content);
+ repodata_set_poolstr(pd->data, handle, SOLVABLE_DISTRIBUTION, content);
break;
case STATE_URL:
- if (pd->content[0])
- repodata_set_str(pd->data, handle, SOLVABLE_URL, pd->content);
+ if (*content)
+ repodata_set_str(pd->data, handle, SOLVABLE_URL, content);
break;
case STATE_PACKAGER:
- if (pd->content[0])
- repodata_set_poolstr(pd->data, handle, SOLVABLE_PACKAGER, pd->content);
+ if (*content)
+ repodata_set_poolstr(pd->data, handle, SOLVABLE_PACKAGER, content);
break;
case STATE_SOURCERPM:
- if (pd->content[0])
- repodata_set_sourcepkg(pd->data, handle, pd->content);
+ if (*content)
+ repodata_set_sourcepkg(pd->data, handle, content);
break;
case STATE_RELNOTESURL:
- if (pd->content[0])
+ if (*content)
{
- repodata_add_poolstr_array(pd->data, handle, PRODUCT_URL, pd->content);
+ repodata_add_poolstr_array(pd->data, handle, PRODUCT_URL, content);
repodata_add_idarray(pd->data, handle, PRODUCT_URL_TYPE, pool_str2id(pool, "releasenotes", 1));
}
break;
case STATE_UPDATEURL:
- if (pd->content[0])
+ if (*content)
{
- repodata_add_poolstr_array(pd->data, handle, PRODUCT_URL, pd->content);
+ repodata_add_poolstr_array(pd->data, handle, PRODUCT_URL, content);
repodata_add_idarray(pd->data, handle, PRODUCT_URL_TYPE, pool_str2id(pool, "update", 1));
}
break;
case STATE_OPTIONALURL:
- if (pd->content[0])
+ if (*content)
{
- repodata_add_poolstr_array(pd->data, handle, PRODUCT_URL, pd->content);
+ repodata_add_poolstr_array(pd->data, handle, PRODUCT_URL, content);
repodata_add_idarray(pd->data, handle, PRODUCT_URL_TYPE, pool_str2id(pool, "optional", 1));
}
break;
case STATE_FLAG:
- if (pd->content[0])
- repodata_add_poolstr_array(pd->data, handle, PRODUCT_FLAGS, pd->content);
+ if (*content)
+ repodata_add_poolstr_array(pd->data, handle, PRODUCT_FLAGS, content);
break;
case STATE_EULA:
- if (pd->content[0])
- repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_EULA, pd->tmplang), pd->content);
+ if (*content)
+ repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_EULA, pd->tmplang), content);
break;
case STATE_KEYWORD:
- if (pd->content[0])
- repodata_add_poolstr_array(pd->data, handle, SOLVABLE_KEYWORDS, pd->content);
+ if (*content)
+ repodata_add_poolstr_array(pd->data, handle, SOLVABLE_KEYWORDS, content);
break;
case STATE_DISKUSAGE:
- if (pd->ndirs)
- commit_diskusage(pd, handle);
+ if (pd->diskusageq.count)
+ repodata_add_diskusage(pd->data, handle, &pd->diskusageq);
break;
case STATE_ORDER:
- if (pd->content[0])
- repodata_set_str(pd->data, handle, SOLVABLE_ORDER, pd->content);
+ if (*content)
+ repodata_set_str(pd->data, handle, SOLVABLE_ORDER, content);
break;
case STATE_CHANGELOG:
- repodata_set_str(pd->data, pd->changelog_handle, SOLVABLE_CHANGELOG_TEXT, pd->content);
+ repodata_set_str(pd->data, pd->changelog_handle, SOLVABLE_CHANGELOG_TEXT, content);
repodata_add_flexarray(pd->data, handle, SOLVABLE_CHANGELOG, pd->changelog_handle);
pd->changelog_handle = 0;
break;
default:
break;
}
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
- /* fprintf(stderr, "back from known %d %d %d\n", pd->state, pd->depth, pd->statedepth); */
}
-
-/*
- * characterData
- * XML callback
- *
- */
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+static void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- struct parsedata *pd = userData;
- int l;
- char *c;
-
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = solv_realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
+ struct parsedata *pd = xmlp->userdata;
+ pd->ret = pool_error(pd->pool, -1, "repo_rpmmd: %s at line %u:%u", errstr, line, column);
}
/*-----------------------------------------------*/
-/* 'main' */
-
-#define BUFF_SIZE 8192
/*
* repo_add_rpmmd
@@ -1319,32 +1111,20 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags)
{
Pool *pool = repo->pool;
struct parsedata pd;
- char buf[BUFF_SIZE];
- int i, l;
- struct stateswitch *sw;
Repodata *data;
unsigned int now;
- XML_Parser parser;
now = solv_timems(0);
data = repo_add_repodata(repo, flags);
memset(&pd, 0, sizeof(pd));
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
pd.pool = pool;
pd.repo = repo;
pd.data = data;
- pd.content = solv_malloc(256);
- pd.acontent = 256;
- pd.lcontent = 0;
pd.kind = 0;
pd.language = language && *language && strcmp(language, "en") != 0 ? language : 0;
+ queue_init(&pd.diskusageq);
init_cshash(&pd);
if ((flags & REPO_EXTEND_SOLVABLES) != 0)
@@ -1354,28 +1134,15 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags)
fill_cshash_from_repo(&pd);
}
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd);
- pd.parser = &parser;
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pd.ret = pool_error(pool, -1, "repo_rpmmd: %s at line %u:%u", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
- solv_free(pd.content);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
+
solv_free(pd.lastdirstr);
join_freemem(&pd.jd);
free_cshash(&pd);
repodata_free_dircache(data);
+ queue_free(&pd.diskusageq);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
diff --git a/ext/repo_susetags.c b/ext/repo_susetags.c
index 83967e0..41c7a78 100644
--- a/ext/repo_susetags.c
+++ b/ext/repo_susetags.c
@@ -6,8 +6,6 @@
*/
#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -21,6 +19,7 @@
#ifdef ENABLE_COMPLEX_DEPS
#include "pool_parserpmrichdep.h"
#endif
+#include "repodata_diskusage.h"
struct datashare {
Id name;
@@ -38,8 +37,7 @@ struct parsedata {
int last_found_source;
struct datashare *share_with;
int nshare;
- Id (*dirs)[3]; /* dirid, size, nfiles */
- int ndirs;
+ Queue diskusageq;
struct joindata jd;
char *language; /* the default language */
Id langcache[ID_NUM_INTERNAL]; /* cache for the default language */
@@ -180,39 +178,6 @@ add_source(struct parsedata *pd, char *line, Solvable *s, Id handle)
repodata_set_constantid(pd->data, handle, SOLVABLE_SOURCEARCH, arch);
}
-/*
- * add_dirline
- * add a line with directory information
- *
- */
-
-static void
-add_dirline(struct parsedata *pd, char *line)
-{
- char *sp[6];
- long filesz;
- long filenum;
- Id dirid;
- if (split(line, sp, 6) != 5)
- return;
- pd->dirs = solv_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
- filesz = strtol(sp[1], 0, 0);
- filesz += strtol(sp[2], 0, 0);
- filenum = strtol(sp[3], 0, 0);
- filenum += strtol(sp[4], 0, 0);
- /* hack: we know that there's room for a / */
- if (*sp[0] != '/')
- *--sp[0] = '/';
- dirid = repodata_str2dir(pd->data, sp[0], 1);
-#if 0
-fprintf(stderr, "%s -> %d\n", sp[0], dirid);
-#endif
- pd->dirs[pd->ndirs][0] = dirid;
- pd->dirs[pd->ndirs][1] = filesz;
- pd->dirs[pd->ndirs][2] = filenum;
- pd->ndirs++;
-}
-
static void
set_checksum(struct parsedata *pd, Repodata *data, Id handle, Id keyname, char *line)
{
@@ -238,86 +203,6 @@ set_checksum(struct parsedata *pd, Repodata *data, Id handle, Id keyname, char *
}
-/*
- * id3_cmp
- * compare
- *
- */
-
-static int
-id3_cmp(const void *v1, const void *v2, void *dp)
-{
- Id *i1 = (Id*)v1;
- Id *i2 = (Id*)v2;
- return i1[0] - i2[0];
-}
-
-
-/*
- * commit_diskusage
- *
- */
-
-static void
-commit_diskusage(struct parsedata *pd, Id handle)
-{
- int i;
- Dirpool *dp = &pd->data->dirpool;
- /* Now sort in dirid order. This ensures that parents come before
- their children. */
- if (pd->ndirs > 1)
- solv_sort(pd->dirs, pd->ndirs, sizeof(pd->dirs[0]), id3_cmp, 0);
- /* Substract leaf numbers from all parents to make the numbers
- non-cumulative. This must be done post-order (i.e. all leafs
- adjusted before parents). We ensure this by starting at the end of
- the array moving to the start, hence seeing leafs before parents. */
- for (i = pd->ndirs; i--;)
- {
- Id p = dirpool_parent(dp, pd->dirs[i][0]);
- int j = i;
- for (; p; p = dirpool_parent(dp, p))
- {
- for (; j--;)
- if (pd->dirs[j][0] == p)
- break;
- if (j >= 0)
- {
- if (pd->dirs[j][1] < pd->dirs[i][1])
- pd->dirs[j][1] = 0;
- else
- pd->dirs[j][1] -= pd->dirs[i][1];
- if (pd->dirs[j][2] < pd->dirs[i][2])
- pd->dirs[j][2] = 0;
- else
- pd->dirs[j][2] -= pd->dirs[i][2];
- }
- else
- /* Haven't found this parent in the list, look further if
- we maybe find the parents parent. */
- j = i;
- }
- }
-#if 0
- char sbuf[1024];
- char *buf = sbuf;
- unsigned slen = sizeof(sbuf);
- for (i = 0; i < pd->ndirs; i++)
- {
- dir2str(attr, pd->dirs[i][0], &buf, &slen);
- fprintf(stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
- }
- if (buf != sbuf)
- free (buf);
-#endif
- for (i = 0; i < pd->ndirs; i++)
- if (pd->dirs[i][1] || pd->dirs[i][2])
- {
- repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
- }
- pd->ndirs = 0;
-}
-
-
/* Unfortunately "a"[0] is no constant expression in the C languages,
so we need to pass the four characters individually :-/ */
#define CTAG(a,b,c,d) ((unsigned)(((unsigned char)a) << 24) \
@@ -385,13 +270,13 @@ finish_solvable(struct parsedata *pd, Solvable *s, Offset freshens)
}
pd->nfilelist = 0;
}
- /* A self provide, except for source packages. This is harmless
+ /* Add self provide, except for source packages. This is harmless
to do twice (in case we see the same package twice). */
if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
repo_rewrite_suse_deps(s, freshens);
- if (pd->ndirs)
- commit_diskusage(pd, handle);
+ if (pd->diskusageq.count)
+ repodata_add_diskusage(pd->data, handle, &pd->diskusageq);
}
static Hashtable
@@ -484,7 +369,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
int indelta = 0;
int last_found_pack = 0;
Id first_new_pkg = 0;
- char *sp[5];
+ char *sp[6];
struct parsedata pd;
Repodata *data = 0;
Id handle = 0;
@@ -509,6 +394,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
pd.data = data;
pd.flags = flags;
pd.language = language && *language ? solv_strdup(language) : 0;
+ queue_init(&pd.diskusageq);
linep = line;
s = 0;
@@ -1034,8 +920,22 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
continue;
}
case CTAG('=', 'D', 'i', 'r'):
- add_dirline(&pd, line + 6);
- continue;
+ if (split(line + 6, sp, 6) == 5)
+ {
+ long filesz, filenum;
+ Id did;
+
+ filesz = strtol(sp[1], 0, 0);
+ filesz += strtol(sp[2], 0, 0);
+ filenum = strtol(sp[3], 0, 0);
+ filenum += strtol(sp[4], 0, 0);
+ if (*sp[0] != '/')
+ *--sp[0] = '/'; /* hack: we know that there's room for a / */
+ did = repodata_str2dir(data, sp[0], 1);
+ queue_push(&pd.diskusageq, did);
+ queue_push2(&pd.diskusageq, (Id)filesz, (Id)filenum);
+ }
+ break;
case CTAG('=', 'C', 'a', 't'):
repodata_set_poolstr(data, handle, langtag(&pd, SOLVABLE_CATEGORY, line_lang), line + 3 + keylen);
break;
@@ -1065,27 +965,22 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
case CTAG('=', 'F', 'l', 's'):
{
- char *p = strrchr(line + 6, '/');
+ char *p, *file = line + 6;
Id did;
- /* strip trailing slash */
- if (p && p != line + 6 && !p[1])
+
+ if (*file != '/')
+ *--file = '/'; /* hack: we know there is room */
+ p = strrchr(file, '/');
+ /* strip trailing slashes */
+ while (p != file && !p[1])
{
*p = 0;
- p = strrchr(line + 6, '/');
- }
- if (p)
- {
- *p++ = 0;
- did = repodata_str2dir(data, line + 6, 1);
- }
- else
- {
- p = line + 6;
- did = 0;
+ p = strrchr(file, '/');
}
- if (!did)
- did = repodata_str2dir(data, "/", 1);
+ *p++ = 0;
+ did = repodata_str2dir(data, *file ? file : "/", 1);
repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, p);
+ line[5] = ' ';
break;
}
case CTAG('=', 'H', 'd', 'r'):
@@ -1178,5 +1073,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int
solv_free(pd.language);
solv_free(line);
join_freemem(&pd.jd);
+ queue_free(&pd.diskusageq);
return pd.ret;
}
diff --git a/ext/repo_updateinfoxml.c b/ext/repo_updateinfoxml.c
index 6af74f2..7ba0062 100644
--- a/ext/repo_updateinfoxml.c
+++ b/ext/repo_updateinfoxml.c
@@ -8,16 +8,14 @@
#define _GNU_SOURCE
#define _XOPEN_SOURCE /* glibc2 needs this */
#include <sys/types.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <expat.h>
#include <time.h>
#include "pool.h"
#include "repo.h"
+#include "solv_xmlparser.h"
#include "repo_updateinfoxml.h"
#define DISABLE_SPLIT
#include "tools_util.h"
@@ -75,16 +73,7 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-
-/* !! must be sorted by first column !! */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
{ STATE_START, "updates", STATE_UPDATES, 0 },
{ STATE_START, "update", STATE_UPDATE, 0 },
{ STATE_UPDATES, "update", STATE_UPDATE, 0 },
@@ -112,13 +101,6 @@ static struct stateswitch stateswitches[] = {
struct parsedata {
int ret;
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
Pool *pool;
Repo *repo;
Repodata *data;
@@ -126,10 +108,8 @@ struct parsedata {
Solvable *solvable;
time_t buildtime;
Id collhandle;
+ struct solv_xmlparser xmlp;
struct joindata jd;
-
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
};
/*
@@ -161,7 +141,7 @@ static Id
makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
{
const char *e, *v, *r, *v2;
- char *c;
+ char *c, *space;
int l;
e = v = r = 0;
@@ -190,12 +170,8 @@ makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
l += strlen(v);
if (r)
l += strlen(r) + 1;
- if (l > pd->acontent)
- {
- pd->content = realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content;
+
+ c = space = solv_xmlparser_contentspace(&pd->xmlp, l);
if (e)
{
strcpy(c, e);
@@ -214,60 +190,25 @@ makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
c += strlen(c);
}
*c = 0;
- if (!*pd->content)
+ if (!*space)
return 0;
#if 0
- fprintf(stderr, "evr: %s\n", pd->content);
+ fprintf(stderr, "evr: %s\n", space);
#endif
- return pool_str2id(pool, pd->content, 1);
+ return pool_str2id(pool, space, 1);
}
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *solvable = pd->solvable;
- struct stateswitch *sw;
- /*const char *str; */
-
-#if 0
- fprintf(stderr, "start: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
- pd->depth++;
- if (!pd->swtab[pd->state])
- return;
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */
- if (!strcmp(sw->ename, name))
- break;
-
- if (sw->from != pd->state)
+ switch(state)
{
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
-
- switch(pd->state)
- {
- case STATE_START:
- break;
- case STATE_UPDATES:
- break;
/*
* <update from="rel-eng@fedoraproject.org"
* status="stable"
@@ -297,26 +238,11 @@ startElement(void *userData, const char *name, const char **atts)
pd->buildtime = (time_t)0;
}
break;
- /* <id>FEDORA-2007-4594</id> */
- case STATE_ID:
- break;
- /* <title>imlib-1.9.15-6.fc8</title> */
- case STATE_TITLE:
- break;
- /* <release>Fedora 8</release> */
- case STATE_RELEASE:
- break;
- /* <issued date="2008-03-21 21:36:55"/>
- */
+
case STATE_ISSUED:
case STATE_UPDATED:
{
- const char *date = 0;
- for (; *atts; atts += 2)
- {
- if (!strcmp(*atts, "date"))
- date = atts[1];
- }
+ const char *date = solv_xmlparser_find_attr("date", atts);
if (date)
{
time_t t = datestr2timestamp(date);
@@ -325,13 +251,7 @@ startElement(void *userData, const char *name, const char **atts)
}
}
break;
- case STATE_REFERENCES:
- break;
- /* <reference href="https://bugzilla.redhat.com/show_bug.cgi?id=330471"
- * id="330471"
- * title="LDAP schema file missing for dhcpd"
- * type="bugzilla"/>
- */
+
case STATE_REFERENCE:
{
const char *href = 0, *id = 0, *title = 0, *type = 0;
@@ -359,20 +279,7 @@ startElement(void *userData, const char *name, const char **atts)
repodata_add_flexarray(pd->data, pd->handle, UPDATE_REFERENCE, refhandle);
}
break;
- /* <description>This update ...</description> */
- case STATE_DESCRIPTION:
- break;
- /* <message type="confirm">This update ...</message> */
- case STATE_MESSAGE:
- break;
- case STATE_PKGLIST:
- break;
- /* <collection short="F8" */
- case STATE_COLLECTION:
- break;
- /* <name>Fedora 8</name> */
- case STATE_NAME:
- break;
+
/* <package arch="ppc64" name="imlib-debuginfo" release="6.fc8"
* src="http://download.fedoraproject.org/pub/fedora/linux/updates/8/ppc64/imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm"
* version="1.9.15">
@@ -414,19 +321,7 @@ startElement(void *userData, const char *name, const char **atts)
repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_ARCH, a);
break;
}
- /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */
- /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */
- case STATE_FILENAME:
- break;
- /* <reboot_suggested>True</reboot_suggested> */
- case STATE_REBOOT:
- break;
- /* <restart_suggested>True</restart_suggested> */
- case STATE_RESTART:
- break;
- /* <relogin_suggested>True</relogin_suggested> */
- case STATE_RELOGIN:
- break;
+
default:
break;
}
@@ -434,34 +329,16 @@ startElement(void *userData, const char *name, const char **atts)
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
Repo *repo = pd->repo;
-#if 0
- fprintf(stderr, "end: %s\n", name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
-#if 0
- fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-#endif
- return;
- }
-
- pd->depth--;
- pd->statedepth--;
- switch (pd->state)
+ switch (state)
{
- case STATE_START:
- break;
- case STATE_UPDATES:
- break;
case STATE_UPDATE:
s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
if (pd->buildtime)
@@ -470,80 +347,75 @@ endElement(void *userData, const char *name)
pd->buildtime = (time_t)0;
}
break;
+
case STATE_ID:
- s->name = pool_str2id(pool, join2(&pd->jd, "patch", ":", pd->content), 1);
+ s->name = pool_str2id(pool, join2(&pd->jd, "patch", ":", content), 1);
break;
+
/* <title>imlib-1.9.15-6.fc8</title> */
case STATE_TITLE:
- while (pd->lcontent > 0 && pd->content[pd->lcontent - 1] == '\n')
- pd->content[--pd->lcontent] = 0;
- repodata_set_str(pd->data, pd->handle, SOLVABLE_SUMMARY, pd->content);
+ /* strip trailing newlines */
+ while (pd->xmlp.lcontent > 0 && content[pd->xmlp.lcontent - 1] == '\n')
+ content[--pd->xmlp.lcontent] = 0;
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_SUMMARY, content);
break;
+
case STATE_SEVERITY:
- repodata_set_poolstr(pd->data, pd->handle, UPDATE_SEVERITY, pd->content);
+ repodata_set_poolstr(pd->data, pd->handle, UPDATE_SEVERITY, content);
break;
+
case STATE_RIGHTS:
- repodata_set_poolstr(pd->data, pd->handle, UPDATE_RIGHTS, pd->content);
- break;
- /*
- * <release>Fedora 8</release>
- */
- case STATE_RELEASE:
- break;
- case STATE_ISSUED:
- break;
- case STATE_REFERENCES:
- break;
- case STATE_REFERENCE:
+ repodata_set_poolstr(pd->data, pd->handle, UPDATE_RIGHTS, content);
break;
+
/*
* <description>This update ...</description>
*/
case STATE_DESCRIPTION:
- repodata_set_str(pd->data, pd->handle, SOLVABLE_DESCRIPTION, pd->content);
+ repodata_set_str(pd->data, pd->handle, SOLVABLE_DESCRIPTION, content);
break;
+
/*
* <message>Warning! ...</message>
*/
case STATE_MESSAGE:
- repodata_set_str(pd->data, pd->handle, UPDATE_MESSAGE, pd->content);
- break;
- case STATE_PKGLIST:
- break;
- case STATE_COLLECTION:
- break;
- case STATE_NAME:
+ repodata_set_str(pd->data, pd->handle, UPDATE_MESSAGE, content);
break;
+
case STATE_PACKAGE:
repodata_add_flexarray(pd->data, pd->handle, UPDATE_COLLECTION, pd->collhandle);
pd->collhandle = 0;
break;
+
/* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */
/* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */
case STATE_FILENAME:
- repodata_set_str(pd->data, pd->collhandle, UPDATE_COLLECTION_FILENAME, pd->content);
+ repodata_set_str(pd->data, pd->collhandle, UPDATE_COLLECTION_FILENAME, content);
break;
+
/* <reboot_suggested>True</reboot_suggested> */
case STATE_REBOOT:
- if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1')
+ if (content[0] == 'T' || content[0] == 't'|| content[0] == '1')
{
/* FIXME: this is per-package, the global flag should be computed at runtime */
repodata_set_void(pd->data, pd->handle, UPDATE_REBOOT);
repodata_set_void(pd->data, pd->collhandle, UPDATE_REBOOT);
}
break;
+
/* <restart_suggested>True</restart_suggested> */
case STATE_RESTART:
- if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1')
+ if (content[0] == 'T' || content[0] == 't'|| content[0] == '1')
{
/* FIXME: this is per-package, the global flag should be computed at runtime */
repodata_set_void(pd->data, pd->handle, UPDATE_RESTART);
repodata_set_void(pd->data, pd->collhandle, UPDATE_RESTART);
}
break;
+
/* <relogin_suggested>True</relogin_suggested> */
case STATE_RELOGIN:
- if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1')
+ if (content[0] == 'T' || content[0] == 't'|| content[0] == '1')
{
/* FIXME: this is per-package, the global flag should be computed at runtime */
repodata_set_void(pd->data, pd->handle, UPDATE_RELOGIN);
@@ -553,86 +425,31 @@ endElement(void *userData, const char *name)
default:
break;
}
-
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
}
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
+static void
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- struct parsedata *pd = userData;
- int l;
- char *c;
-
- if (!pd->docontent)
- {
-#if 0
- fprintf(stderr, "Content: [%d]'%.*s'\n", pd->state, len, s);
-#endif
- return;
- }
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
+ struct parsedata *pd = xmlp->userdata;
+ pd->ret = pool_error(pd->pool, -1, "repo_updateinfoxml: %s at line %u:%u", errstr, line, column);
}
-
-#define BUFF_SIZE 8192
-
int
repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags)
{
Pool *pool = repo->pool;
- struct parsedata pd;
- char buf[BUFF_SIZE];
- int i, l;
- struct stateswitch *sw;
Repodata *data;
- XML_Parser parser;
+ struct parsedata pd;
data = repo_add_repodata(repo, flags);
memset(&pd, 0, sizeof(pd));
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
pd.pool = pool;
pd.repo = repo;
pd.data = data;
-
- pd.content = malloc(256);
- pd.acontent = 256;
- pd.lcontent = 0;
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, &pd);
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
- for (;;)
- {
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pd.ret = pool_error(pool, -1, "repo_updateinfoxml: %s at line %u:%u", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- break;
- }
- if (l == 0)
- break;
- }
- XML_ParserFree(parser);
- free(pd.content);
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
+ solv_xmlparser_parse(&pd.xmlp, fp);
+ solv_xmlparser_free(&pd.xmlp);
join_freemem(&pd.jd);
if (!(flags & REPO_NO_INTERNALIZE))
diff --git a/ext/repo_zyppdb.c b/ext/repo_zyppdb.c
index 5200c29..d73a900 100644
--- a/ext/repo_zyppdb.c
+++ b/ext/repo_zyppdb.c
@@ -4,7 +4,6 @@
* Parses legacy /var/lib/zypp/db/products/... files.
* They are old (pre Code11) product descriptions. See bnc#429177
*
- *
* Copyright (c) 2008, Novell Inc.
*
* This program is licensed under the BSD license, read LICENSE.BSD
@@ -14,20 +13,17 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <dirent.h>
-#include <expat.h>
#include <errno.h>
#include "pool.h"
#include "repo.h"
#include "util.h"
+#include "solv_xmlparser.h"
#define DISABLE_SPLIT
#include "tools_util.h"
#include "repo_zyppdb.h"
@@ -45,15 +41,7 @@ enum state {
NUMSTATES
};
-struct stateswitch {
- enum state from;
- char *ename;
- enum state to;
- int docontent;
-};
-
-/* !! must be sorted by first column !! */
-static struct stateswitch stateswitches[] = {
+static struct solv_xmlparser_element stateswitches[] = {
{ STATE_START, "product", STATE_PRODUCT, 0 },
{ STATE_PRODUCT, "name", STATE_NAME, 1 },
{ STATE_PRODUCT, "version", STATE_VERSION, 0 },
@@ -65,101 +53,32 @@ static struct stateswitch stateswitches[] = {
};
struct parsedata {
- int depth;
- enum state state;
- int statedepth;
- char *content;
- int lcontent;
- int acontent;
- int docontent;
Pool *pool;
Repo *repo;
Repodata *data;
-
- struct stateswitch *swtab[NUMSTATES];
- enum state sbtab[NUMSTATES];
- struct joindata jd;
-
+ const char *filename;
const char *tmplang;
-
Solvable *solvable;
Id handle;
+ struct solv_xmlparser xmlp;
+ struct joindata jd;
};
-/*
- * find_attr
- * find value for xml attribute
- * I: txt, name of attribute
- * I: atts, list of key/value attributes
- * O: pointer to value of matching key, or NULL
- *
- */
-
-static inline const char *
-find_attr(const char *txt, const char **atts)
-{
- for (; *atts; atts += 2)
- {
- if (!strcmp(*atts, txt))
- return atts[1];
- }
- return 0;
-}
-
-
-/*
- * XML callback: startElement
- */
-static void XMLCALL
-startElement(void *userData, const char *name, const char **atts)
+static void
+startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Pool *pool = pd->pool;
Solvable *s = pd->solvable;
- struct stateswitch *sw;
-
-#if 0
- fprintf(stderr, "start: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth++;
- return;
- }
-
- pd->depth++;
- if (!pd->swtab[pd->state]) /* no statetable -> no substates */
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */
- if (!strcmp(sw->ename, name))
- break;
-
- if (sw->from != pd->state)
- {
-#if 0
- fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
-#endif
- return;
- }
- pd->state = sw->to;
- pd->docontent = sw->docontent;
- pd->statedepth = pd->depth;
- pd->lcontent = 0;
- *pd->content = 0;
- switch(pd->state)
+ switch(state)
{
case STATE_PRODUCT:
{
/* parse 'type' */
- const char *type = find_attr("type", atts);
+ const char *type = solv_xmlparser_find_attr("type", atts);
s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
pd->handle = s - pool->solvables;
if (type)
@@ -168,15 +87,14 @@ startElement(void *userData, const char *name, const char **atts)
break;
case STATE_VERSION:
{
- const char *ver = find_attr("ver", atts);
- const char *rel = find_attr("rel", atts);
- /* const char *epoch = find_attr("epoch", atts); ignored */
+ const char *ver = solv_xmlparser_find_attr("ver", atts);
+ const char *rel = solv_xmlparser_find_attr("rel", atts);
+ /* const char *epoch = solv_xmlparser_find_attr("epoch", atts); ignored */
s->evr = makeevr(pd->pool, join2(&pd->jd, ver, "-", rel));
}
break;
- /* <summary lang="xy">... */
- case STATE_SUMMARY:
- pd->tmplang = join_dup(&pd->jd, find_attr("lang", atts));
+ case STATE_SUMMARY: /* <summary lang="xy">... */
+ pd->tmplang = join_dup(&pd->jd, solv_xmlparser_find_attr("lang", atts));
break;
default:
break;
@@ -184,28 +102,13 @@ startElement(void *userData, const char *name, const char **atts)
}
-static void XMLCALL
-endElement(void *userData, const char *name)
+static void
+endElement(struct solv_xmlparser *xmlp, int state, char *content)
{
- struct parsedata *pd = userData;
+ struct parsedata *pd = xmlp->userdata;
Solvable *s = pd->solvable;
-#if 0
- fprintf(stderr, "end: [%d]%s\n", pd->state, name);
-#endif
- if (pd->depth != pd->statedepth)
- {
- pd->depth--;
-#if 0
- fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
-#endif
- return;
- }
-
- pd->depth--;
- pd->statedepth--;
-
- switch (pd->state)
+ switch (state)
{
case STATE_PRODUCT:
if (!s->arch)
@@ -217,89 +120,34 @@ endElement(void *userData, const char *name)
pd->solvable = 0;
break;
case STATE_NAME:
- s->name = pool_str2id(pd->pool, join2(&pd->jd, "product", ":", pd->content), 1);
+ s->name = pool_str2id(pd->pool, join2(&pd->jd, "product", ":", content), 1);
break;
case STATE_ARCH:
- s->arch = pool_str2id(pd->pool, pd->content, 1);
+ s->arch = pool_str2id(pd->pool, content, 1);
break;
case STATE_SUMMARY:
- repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), pd->content);
+ repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), content);
break;
case STATE_VENDOR:
- s->vendor = pool_str2id(pd->pool, pd->content, 1);
+ s->vendor = pool_str2id(pd->pool, content, 1);
break;
case STATE_INSTALLTIME:
- repodata_set_num(pd->data, pd->handle, SOLVABLE_INSTALLTIME, atol(pd->content));
+ repodata_set_num(pd->data, pd->handle, SOLVABLE_INSTALLTIME, atol(content));
default:
break;
}
-
- pd->state = pd->sbtab[pd->state];
- pd->docontent = 0;
-
-#if 0
- fprintf(stderr, "end: [%s] -> %d\n", name, pd->state);
-#endif
-}
-
-
-static void XMLCALL
-characterData(void *userData, const XML_Char *s, int len)
-{
- struct parsedata *pd = userData;
- int l;
- char *c;
- if (!pd->docontent)
- return;
- l = pd->lcontent + len + 1;
- if (l > pd->acontent)
- {
- pd->content = realloc(pd->content, l + 256);
- pd->acontent = l + 256;
- }
- c = pd->content + pd->lcontent;
- pd->lcontent += len;
- while (len-- > 0)
- *c++ = *s++;
- *c = 0;
}
-#define BUFF_SIZE 8192
-
-
-/*
- * add single product to repo
- *
- */
-
static void
-add_zyppdb_product(struct parsedata *pd, FILE *fp)
+errorCallback(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column)
{
- char buf[BUFF_SIZE];
- int l;
-
- XML_Parser parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, pd);
- XML_SetElementHandler(parser, startElement, endElement);
- XML_SetCharacterDataHandler(parser, characterData);
-
- for (;;)
+ struct parsedata *pd = xmlp->userdata;
+ pool_debug(pd->pool, SOLV_ERROR, "repo_zyppdb: %s: %s at line %u:%u\n", pd->filename, errstr, line, column);
+ if (pd->solvable)
{
- l = fread(buf, 1, sizeof(buf), fp);
- if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
- {
- pool_debug(pd->pool, SOLV_ERROR, "repo_zyppdb: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- if (pd->solvable)
- {
- repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1);
- pd->solvable = 0;
- }
- return;
- }
- if (l == 0)
- break;
+ repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1);
+ pd->solvable = 0;
}
- XML_ParserFree(parser);
}
@@ -312,9 +160,7 @@ add_zyppdb_product(struct parsedata *pd, FILE *fp)
int
repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags)
{
- int i;
struct parsedata pd;
- struct stateswitch *sw;
struct dirent *entry;
char *fullpath;
DIR *dir;
@@ -326,16 +172,7 @@ repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags)
pd.repo = repo;
pd.pool = repo->pool;
pd.data = data;
-
- pd.content = malloc(256);
- pd.acontent = 256;
-
- for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
- {
- if (!pd.swtab[sw->from])
- pd.swtab[sw->from] = sw;
- pd.sbtab[sw->to] = sw->from;
- }
+ solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement, errorCallback);
if (flags & REPO_USE_ROOTDIR)
dirpath = pool_prepend_rootdir(repo->pool, dirpath);
@@ -344,21 +181,22 @@ repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags)
{
while ((entry = readdir(dir)))
{
- if (strlen(entry->d_name) < 3)
- continue; /* skip '.' and '..' */
+ if (entry->d_name[0] == '.')
+ continue; /* skip dot files */
fullpath = join2(&pd.jd, dirpath, "/", entry->d_name);
if ((fp = fopen(fullpath, "r")) == 0)
{
pool_error(repo->pool, 0, "%s: %s", fullpath, strerror(errno));
continue;
}
- add_zyppdb_product(&pd, fp);
+ pd.filename = entry->d_name;
+ solv_xmlparser_parse(&pd.xmlp, fp);
fclose(fp);
}
}
closedir(dir);
- free(pd.content);
+ solv_xmlparser_free(&pd.xmlp);
join_freemem(&pd.jd);
if (flags & REPO_USE_ROOTDIR)
solv_free((char *)dirpath);
diff --git a/ext/repodata_diskusage.c b/ext/repodata_diskusage.c
new file mode 100644
index 0000000..fd9c5cc
--- /dev/null
+++ b/ext/repodata_diskusage.c
@@ -0,0 +1,78 @@
+/*
+ * repodata_diskusage.c
+ *
+ * Small helper to convert diskusage data from sustags or rpmmd
+ *
+ * Copyright (c) 2017, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pool.h"
+#include "repo.h"
+#include "util.h"
+#include "repodata_diskusage.h"
+
+/* The queue contains (dirid, kbytes, inodes) triplets */
+
+static int
+add_diskusage_sortfn(const void *ap, const void *bp, void *dp)
+{
+ return *(Id *)ap - *(Id *)bp;
+}
+
+void
+repodata_add_diskusage(Repodata *data, Id handle, Queue *q)
+{
+ int i, j;
+ Dirpool *dp = &data->dirpool;
+
+ /* Sort in dirid order. This ensures that parents come before
+ * their children. */
+ if (q->count > 3)
+ solv_sort(q->elements, q->count / 3, 3 * sizeof(Id), add_diskusage_sortfn, 0);
+ for (i = 3; i < q->count; i += 3)
+ {
+ /* subtract data from parent */
+ Id did = q->elements[i];
+ if (i + 3 < q->count && q->elements[i + 3] == did)
+ {
+ /* identical directory entry! zero this one */
+ q->elements[i + 1] = 0;
+ q->elements[i + 2] = 0;
+ continue;
+ }
+ while (did)
+ {
+ did = dirpool_parent(dp, did);
+ for (j = i - 3; j >= 0; j -= 3)
+ if (q->elements[j] == did)
+ break;
+ if (j >= 0)
+ {
+ if ((unsigned int)q->elements[j + 1] > (unsigned int)q->elements[i + 1])
+ q->elements[j + 1] -= q->elements[i + 1];
+ else
+ q->elements[j + 1] = 0;
+ if ((unsigned int)q->elements[j + 2] > (unsigned int)q->elements[i + 2])
+ q->elements[j + 2] -= q->elements[i + 2];
+ else
+ q->elements[j + 2] = 0;
+ break;
+ }
+ }
+ }
+ /* now commit data */
+ for (i = 0; i < q->count; i += 3)
+ if (q->elements[i + 1] || q->elements[i + 2])
+ repodata_add_dirnumnum(data, handle, SOLVABLE_DISKUSAGE, q->elements[i], q->elements[i + 1], q->elements[i + 2]);
+ /* empty queue */
+ queue_empty(q);
+}
+
diff --git a/ext/repodata_diskusage.h b/ext/repodata_diskusage.h
new file mode 100644
index 0000000..1beafea
--- /dev/null
+++ b/ext/repodata_diskusage.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2017, SUSE Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+extern void repodata_add_diskusage(Repodata *data, Id handle, Queue *q);
+
+
diff --git a/ext/solv_xfopen.c b/ext/solv_xfopen.c
index b0421bf..967984e 100644
--- a/ext/solv_xfopen.c
+++ b/ext/solv_xfopen.c
@@ -10,30 +10,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <zlib.h>
#include <fcntl.h>
#include "solv_xfopen.h"
#include "util.h"
-/* Evil hack for Haiku: fopencookie() is implemented internally, but not
- exported by a header. */
-#ifdef __HAIKU__
-
-typedef struct {
- ssize_t (*read)(void*, char*, size_t);
- ssize_t (*write)(void*, const char*, size_t);
- int (*seek)(off_t*, int);
- int (*close)(void*);
-} cookie_io_functions_t;
-
-
-FILE *fopencookie(void*, const char*, cookie_io_functions_t);
-
-#endif /* __HAIKU__ */
-
-
static FILE *cookieopen(void *cookie, const char *mode,
ssize_t (*cread)(void *, char *, size_t),
ssize_t (*cwrite)(void *, const char *, size_t),
@@ -66,8 +48,12 @@ static FILE *cookieopen(void *cookie, const char *mode,
}
+#ifdef ENABLE_ZLIB_COMPRESSION
+
/* gzip compression */
+#include <zlib.h>
+
static ssize_t cookie_gzread(void *cookie, char *buf, size_t nbytes)
{
return gzread((gzFile)cookie, buf, nbytes);
@@ -95,12 +81,15 @@ static inline FILE *mygzfdopen(int fd, const char *mode)
return cookieopen(gzf, mode, cookie_gzread, cookie_gzwrite, cookie_gzclose);
}
-#ifdef ENABLE_BZIP2_COMPRESSION
+#endif
-#include <bzlib.h>
+
+#ifdef ENABLE_BZIP2_COMPRESSION
/* bzip2 compression */
+#include <bzlib.h>
+
static ssize_t cookie_bzread(void *cookie, char *buf, size_t nbytes)
{
return BZ2_bzread((BZFILE *)cookie, buf, nbytes);
@@ -134,10 +123,10 @@ static inline FILE *mybzfdopen(int fd, const char *mode)
#ifdef ENABLE_LZMA_COMPRESSION
-#include <lzma.h>
-
/* lzma code written by me in 2008 for rpm's rpmio.c */
+#include <lzma.h>
+
typedef struct lzfile {
unsigned char buf[1 << 15];
lzma_stream strm;
@@ -338,8 +327,13 @@ solv_xfopen(const char *fn, const char *mode)
if (!mode)
mode = "r";
suf = strrchr(fn, '.');
+#ifdef ENABLE_ZLIB_COMPRESSION
if (suf && !strcmp(suf, ".gz"))
return mygzfopen(fn, mode);
+#else
+ if (suf && !strcmp(suf, ".gz"))
+ return 0;
+#endif
#ifdef ENABLE_LZMA_COMPRESSION
if (suf && !strcmp(suf, ".xz"))
return myxzfopen(fn, mode);
@@ -384,8 +378,13 @@ solv_xfopen_fd(const char *fn, int fd, const char *mode)
else
mode = simplemode = "r";
}
+#ifdef ENABLE_ZLIB_COMPRESSION
if (suf && !strcmp(suf, ".gz"))
return mygzfdopen(fd, simplemode);
+#else
+ return 0;
+ if (suf && !strcmp(suf, ".gz"))
+#endif
#ifdef ENABLE_LZMA_COMPRESSION
if (suf && !strcmp(suf, ".xz"))
return myxzfdopen(fd, simplemode);
@@ -413,8 +412,12 @@ solv_xfopen_iscompressed(const char *fn)
const char *suf = fn ? strrchr(fn, '.') : 0;
if (!suf)
return 0;
+#ifdef ENABLE_ZLIB_COMPRESSION
if (!strcmp(suf, ".gz"))
return 1;
+#else
+ return -1;
+#endif
if (!strcmp(suf, ".xz") || !strcmp(suf, ".lzma"))
#ifdef ENABLE_LZMA_COMPRESSION
return 1;
diff --git a/ext/solv_xmlparser.c b/ext/solv_xmlparser.c
new file mode 100644
index 0000000..170520f
--- /dev/null
+++ b/ext/solv_xmlparser.c
@@ -0,0 +1,321 @@
+/*
+ * solv_xmlparser.c
+ *
+ * XML parser abstraction
+ *
+ * Copyright (c) 2017, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef WITH_LIBXML2
+#include <libxml/parser.h>
+#else
+#include <expat.h>
+#endif
+
+#include "util.h"
+#include "queue.h"
+#include "solv_xmlparser.h"
+
+static inline void
+add_contentspace(struct solv_xmlparser *xmlp, int l)
+{
+ l += xmlp->lcontent + 1; /* plus room for trailing zero */
+ if (l > xmlp->acontent)
+ {
+ xmlp->acontent = l + 256;
+ xmlp->content = solv_realloc(xmlp->content, xmlp->acontent);
+ }
+}
+
+
+#ifdef WITH_LIBXML2
+static void
+character_data(void *userData, const xmlChar *s, int len)
+#else
+static void XMLCALL
+character_data(void *userData, const XML_Char *s, int len)
+#endif
+{
+ struct solv_xmlparser *xmlp = userData;
+
+ if (!xmlp->docontent || !len)
+ return;
+ add_contentspace(xmlp, len);
+ memcpy(xmlp->content + xmlp->lcontent, s, len);
+ xmlp->lcontent += len;
+}
+
+#ifdef WITH_LIBXML2
+static void
+start_element(void *userData, const xmlChar *name, const xmlChar **atts)
+#else
+static void XMLCALL
+start_element(void *userData, const char *name, const char **atts)
+#endif
+{
+ struct solv_xmlparser *xmlp = userData;
+ struct solv_xmlparser_element *elements;
+ Id *elementhelper;
+ struct solv_xmlparser_element *el;
+ int i, oldstate;
+
+ if (xmlp->unknowncnt)
+ {
+ xmlp->unknowncnt++;
+ return;
+ }
+ elementhelper = xmlp->elementhelper;
+ elements = xmlp->elements;
+ oldstate = xmlp->state;
+ for (i = elementhelper[xmlp->nelements + oldstate]; i; i = elementhelper[i - 1])
+ if (!strcmp(elements[i - 1].element, (char *)name))
+ break;
+ if (!i)
+ {
+#if 0
+ fprintf(stderr, "into unknown: %s\n", name);
+#endif
+ xmlp->unknowncnt++;
+ return;
+ }
+ el = xmlp->elements + i - 1;
+ queue_push(&xmlp->elementq, xmlp->state);
+ xmlp->state = el->tostate;
+ xmlp->docontent = el->docontent;
+ xmlp->lcontent = 0;
+#ifdef WITH_LIBXML2
+ if (!atts)
+ {
+ static const char *nullattr;
+ atts = (const xmlChar **)&nullattr;
+ }
+#endif
+ if (xmlp->state != oldstate)
+ xmlp->startelement(xmlp, xmlp->state, el->element, (const char **)atts);
+}
+
+#ifdef WITH_LIBXML2
+static void
+end_element(void *userData, const xmlChar *name)
+#else
+static void XMLCALL
+end_element(void *userData, const char *name)
+#endif
+{
+ struct solv_xmlparser *xmlp = userData;
+
+ if (xmlp->unknowncnt)
+ {
+ xmlp->unknowncnt--;
+ xmlp->lcontent = 0;
+ xmlp->docontent = 0;
+ return;
+ }
+ xmlp->content[xmlp->lcontent] = 0;
+ if (xmlp->elementq.count && xmlp->state != xmlp->elementq.elements[xmlp->elementq.count - 1])
+ xmlp->endelement(xmlp, xmlp->state, xmlp->content);
+ xmlp->state = queue_pop(&xmlp->elementq);
+ xmlp->docontent = 0;
+ xmlp->lcontent = 0;
+}
+
+void
+solv_xmlparser_init(struct solv_xmlparser *xmlp,
+ struct solv_xmlparser_element *elements,
+ void *userdata,
+ void (*startelement)(struct solv_xmlparser *, int state, const char *name, const char **atts),
+ void (*endelement)(struct solv_xmlparser *, int state, char *content),
+ void (*errorhandler)(struct solv_xmlparser *, const char *errstr, unsigned int line, unsigned int column))
+{
+ int i, nstates, nelements;
+ struct solv_xmlparser_element *el;
+ Id *elementhelper;
+
+ memset(xmlp, 0, sizeof(*xmlp));
+ nstates = 0;
+ nelements = 0;
+ for (el = elements; el->element; el++)
+ {
+ nelements++;
+ if (el->fromstate > nstates)
+ nstates = el->fromstate;
+ if (el->tostate > nstates)
+ nstates = el->tostate;
+ }
+ nstates++;
+
+ xmlp->elements = elements;
+ xmlp->nelements = nelements;
+ elementhelper = solv_calloc(nelements + nstates, sizeof(Id));
+ for (i = nelements - 1; i >= 0; i--)
+ {
+ int fromstate = elements[i].fromstate;
+ elementhelper[i] = elementhelper[nelements + fromstate];
+ elementhelper[nelements + fromstate] = i + 1;
+ }
+ xmlp->elementhelper = elementhelper;
+ queue_init(&xmlp->elementq);
+ xmlp->acontent = 256;
+ xmlp->content = solv_malloc(xmlp->acontent);
+
+ xmlp->userdata = userdata;
+ xmlp->startelement = startelement;
+ xmlp->endelement = endelement;
+ xmlp->errorhandler = errorhandler;
+}
+
+void
+solv_xmlparser_free(struct solv_xmlparser *xmlp)
+{
+ xmlp->elementhelper = solv_free(xmlp->elementhelper);
+ queue_free(&xmlp->elementq);
+ xmlp->content = solv_free(xmlp->content);
+}
+
+#ifdef WITH_LIBXML2
+
+static inline int
+create_parser(struct solv_xmlparser *xmlp)
+{
+ /* delayed to parse_block so that we have the first bytes */
+ return 1;
+}
+
+static inline void
+free_parser(struct solv_xmlparser *xmlp)
+{
+ if (xmlp->parser)
+ xmlFreeParserCtxt(xmlp->parser);
+ xmlp->parser = 0;
+}
+
+static xmlParserCtxtPtr create_parser_ctx(struct solv_xmlparser *xmlp, char *buf, int l)
+{
+ xmlSAXHandler sax;
+ memset(&sax, 0, sizeof(sax));
+ sax.startElement = start_element;
+ sax.endElement = end_element;
+ sax.characters = character_data;
+ return xmlCreatePushParserCtxt(&sax, xmlp, buf, l, NULL);
+}
+
+static inline int
+parse_block(struct solv_xmlparser *xmlp, char *buf, int l)
+{
+ if (!xmlp->parser)
+ {
+ int l2 = l > 4 ? 4 : 0;
+ xmlp->parser = create_parser_ctx(xmlp, buf, l2);
+ if (!xmlp->parser)
+ {
+ xmlp->errorhandler(xmlp, "could not create parser", 0, 0);
+ return 0;
+ }
+ buf += l2;
+ l -= l2;
+ if (l2 && !l)
+ return 1;
+ }
+ if (xmlParseChunk(xmlp->parser, buf, l, l == 0 ? 1 : 0))
+ {
+ xmlErrorPtr err = xmlCtxtGetLastError(xmlp->parser);
+ xmlp->errorhandler(xmlp, err->message, err->line, err->int2);
+ return 0;
+ }
+ return 1;
+}
+
+unsigned int
+solv_xmlparser_lineno(struct solv_xmlparser *xmlp)
+{
+ return (unsigned int)xmlSAX2GetLineNumber(xmlp->parser);
+}
+
+#else
+
+static inline int
+create_parser(struct solv_xmlparser *xmlp)
+{
+ xmlp->parser = XML_ParserCreate(NULL);
+ if (!xmlp->parser)
+ return 0;
+ XML_SetUserData(xmlp->parser, xmlp);
+ XML_SetElementHandler(xmlp->parser, start_element, end_element);
+ XML_SetCharacterDataHandler(xmlp->parser, character_data);
+ return 1;
+}
+
+static inline void
+free_parser(struct solv_xmlparser *xmlp)
+{
+ XML_ParserFree(xmlp->parser);
+ xmlp->parser = 0;
+}
+
+static inline int
+parse_block(struct solv_xmlparser *xmlp, char *buf, int l)
+{
+ if (XML_Parse(xmlp->parser, buf, l, l == 0) == XML_STATUS_ERROR)
+ {
+ unsigned int line = XML_GetCurrentLineNumber(xmlp->parser);
+ unsigned int column = XML_GetCurrentColumnNumber(xmlp->parser);
+ xmlp->errorhandler(xmlp, XML_ErrorString(XML_GetErrorCode(xmlp->parser)), line, column);
+ return 0;
+ }
+ return 1;
+}
+
+unsigned int
+solv_xmlparser_lineno(struct solv_xmlparser *xmlp)
+{
+ return (unsigned int)XML_GetCurrentLineNumber(xmlp->parser);
+}
+
+#endif
+
+void
+solv_xmlparser_parse(struct solv_xmlparser *xmlp, FILE *fp)
+{
+ char buf[8192];
+ int l;
+
+ xmlp->state = 0;
+ xmlp->unknowncnt = 0;
+ xmlp->docontent = 0;
+ xmlp->lcontent = 0;
+ queue_empty(&xmlp->elementq);
+
+ if (!create_parser(xmlp))
+ {
+ xmlp->errorhandler(xmlp, "could not create xml parser", 0, 0);
+ return;
+ }
+ for (;;)
+ {
+ l = fread(buf, 1, sizeof(buf), fp);
+ if (!parse_block(xmlp, buf, l) || !l)
+ break;
+ }
+ free_parser(xmlp);
+}
+
+char *
+solv_xmlparser_contentspace(struct solv_xmlparser *xmlp, int l)
+{
+ xmlp->lcontent = 0;
+ if (l > xmlp->acontent)
+ {
+ xmlp->acontent = l + 256;
+ xmlp->content = solv_realloc(xmlp->content, xmlp->acontent);
+ }
+ return xmlp->content;
+}
+
diff --git a/ext/solv_xmlparser.h b/ext/solv_xmlparser.h
new file mode 100644
index 0000000..9fb342f
--- /dev/null
+++ b/ext/solv_xmlparser.h
@@ -0,0 +1,52 @@
+
+struct solv_xmlparser_element {
+ int fromstate;
+ char *element;
+ int tostate;
+ int docontent;
+};
+
+struct solv_xmlparser {
+ void *userdata;
+
+ int state;
+ int docontent;
+
+ Queue elementq;
+ int unknowncnt;
+
+ char *content;
+ int lcontent; /* current content length */
+ int acontent; /* allocated content length */
+
+ struct solv_xmlparser_element *elements;
+ int nelements;
+
+ void (*startelement)(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts);
+ void (*endelement)(struct solv_xmlparser *xmlp, int state, char *content);
+ void (*errorhandler)(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column);
+
+ Id *elementhelper;
+ void *parser;
+};
+
+static inline const char *
+solv_xmlparser_find_attr(const char *txt, const char **atts)
+{
+ for (; *atts; atts += 2)
+ if (!strcmp(*atts, txt))
+ return atts[1];
+ return 0;
+}
+
+extern void solv_xmlparser_init(struct solv_xmlparser *xmlp, struct solv_xmlparser_element *elements, void *userdata,
+ void (*startelement)(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts),
+ void (*endelement)(struct solv_xmlparser *xmlp, int state, char *content),
+ void (*errorhandler)(struct solv_xmlparser *xmlp, const char *errstr, unsigned int line, unsigned int column));
+
+extern void solv_xmlparser_free(struct solv_xmlparser *xmlp);
+extern void solv_xmlparser_parse(struct solv_xmlparser *xmlp, FILE *fp);
+unsigned int solv_xmlparser_lineno(struct solv_xmlparser *xmlp);
+char *solv_xmlparser_contentspace(struct solv_xmlparser *xmlp, int l);
+
+
diff --git a/ext/testcase.c b/ext/testcase.c
index ccfcb61..f515057 100644
--- a/ext/testcase.c
+++ b/ext/testcase.c
@@ -7,8 +7,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <limits.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -387,41 +385,42 @@ struct oplist {
{ REL_COMPAT, "compat >=" },
{ REL_KIND, "<KIND>" },
{ REL_ELSE, "<ELSE>" },
+ { REL_ERROR, "<ERROR>" },
{ REL_LT, "<" },
{ 0, 0 }
};
-static const char *
-testcase_dep2str_complex(Pool *pool, Id id, int addparens)
+static char *
+testcase_dep2str_complex(Pool *pool, char *s, Id id, int addparens)
{
Reldep *rd;
- char *s;
const char *s2;
int needparens;
struct oplist *op;
if (!ISRELDEP(id))
- return testcase_id2str(pool, id, 1);
+ {
+ s2 = testcase_id2str(pool, id, 1);
+ s = pool_tmpappend(pool, s, s2, 0);
+ pool_freetmpspace(pool, s2);
+ return s;
+ }
rd = GETRELDEP(pool, id);
/* check for special shortcuts */
if (rd->flags == REL_NAMESPACE && !ISRELDEP(rd->name) && !strncmp(pool_id2str(pool, rd->name), "namespace:", 10))
{
- const char *ns = pool_id2str(pool, rd->name);
- int nslen = strlen(ns);
- /* special namespace formatting */
- const char *evrs = testcase_dep2str_complex(pool, rd->evr, 0);
- s = pool_tmpappend(pool, evrs, ns, "()");
- memmove(s + nslen + 1, s, strlen(s) - nslen - 2);
- memcpy(s, ns, nslen);
- s[nslen] = '(';
- return s;
+ s = pool_tmpappend(pool, s, pool_id2str(pool, rd->name), "(");
+ s = testcase_dep2str_complex(pool, s, rd->evr, 0);
+ return pool_tmpappend(pool, s, ")", 0);
}
if (rd->flags == REL_MULTIARCH && !ISRELDEP(rd->name) && rd->evr == ARCH_ANY)
{
- /* special :any suffix */
- const char *ns = testcase_id2str(pool, rd->name, 1);
- return pool_tmpappend(pool, ns, ":any", 0);
+ /* append special :any suffix */
+ s2 = testcase_id2str(pool, rd->name, 1);
+ s = pool_tmpappend(pool, s, s2, ":any");
+ pool_freetmpspace(pool, s2);
+ return s;
}
needparens = 0;
@@ -432,14 +431,11 @@ testcase_dep2str_complex(Pool *pool, Id id, int addparens)
if (rd->flags > 7 && rd->flags != REL_COMPAT && rd2->flags && rd2->flags <= 7)
needparens = 0;
}
- s = (char *)testcase_dep2str_complex(pool, rd->name, needparens);
if (addparens)
- {
- s = pool_tmpappend(pool, s, "(", 0);
- memmove(s + 1, s, strlen(s + 1));
- s[0] = '(';
- }
+ s = pool_tmpappend(pool, s, "(", 0);
+ s = testcase_dep2str_complex(pool, s, rd->name, needparens);
+
for (op = oplist; op->flags; op++)
if (rd->flags == op->flags)
break;
@@ -470,21 +466,27 @@ testcase_dep2str_complex(Pool *pool, Id id, int addparens)
needparens = 0; /* chain */
}
if (!ISRELDEP(rd->evr))
- s2 = testcase_id2str(pool, rd->evr, 0);
+ {
+ s2 = testcase_id2str(pool, rd->evr, 0);
+ s = pool_tmpappend(pool, s, s2, 0);
+ pool_freetmpspace(pool, s2);
+ }
else
- s2 = testcase_dep2str_complex(pool, rd->evr, needparens);
+ s = (char *)testcase_dep2str_complex(pool, s, rd->evr, needparens);
if (addparens)
- s = pool_tmpappend(pool, s, s2, ")");
- else
- s = pool_tmpappend(pool, s, s2, 0);
- pool_freetmpspace(pool, s2);
+ s = pool_tmpappend(pool, s, ")", 0);
return s;
}
const char *
testcase_dep2str(Pool *pool, Id id)
{
- return testcase_dep2str_complex(pool, id, 0);
+ char *s;
+ if (!ISRELDEP(id))
+ return testcase_id2str(pool, id, 1);
+ s = pool_alloctmpspace(pool, 1);
+ *s = 0;
+ return testcase_dep2str_complex(pool, s, id, 0);
}
@@ -1111,7 +1113,7 @@ testcase_str2job(Pool *pool, const char *str, Id *whatp)
return job;
}
-int
+static int
addselectionjob(Pool *pool, char **pieces, int npieces, Queue *jobqueue)
{
Id job;