#include "pool.h"
#include "repo.h"
-#include "repo_updateinfoxml.h"
-
-//#define DUMPOUT 0
+#include "chksum.h"
+#include "repo_repomdxml.h"
/*
<repomd>
STATE_REPOMD,
STATE_REVISION,
STATE_TAGS,
+ STATE_REPO,
STATE_CONTENT,
STATE_DISTRO,
STATE_UPDATES,
STATE_CHECKSUM,
STATE_TIMESTAMP,
STATE_OPENCHECKSUM,
+ STATE_SIZE,
NUMSTATES
};
{ STATE_START, "suseinfo", STATE_SUSEINFO, 0 },
/* we support the tags element in suseinfo in case
createrepo version does not support it yet */
- { STATE_SUSEINFO, "tags", STATE_TAGS, 0 },
- { STATE_SUSEINFO, "expire", STATE_EXPIRE, 1 },
- { STATE_SUSEINFO, "keywords", STATE_KEYWORDS, 0 },
+ { STATE_SUSEINFO, "tags", STATE_TAGS, 0 },
+ { STATE_SUSEINFO, "expire", STATE_EXPIRE, 1 },
+ { STATE_SUSEINFO, "keywords", STATE_KEYWORDS, 0 },
/* keywords is the suse extension equivalent of
tags/content when this one was not yet available.
- therefore we parse both */
- { STATE_KEYWORDS, "k", STATE_KEYWORD, 1 },
+ therefore we parse both */
+ { STATE_KEYWORDS, "k", STATE_KEYWORD, 1 },
/* standard tags */
{ STATE_REPOMD, "revision", STATE_REVISION, 1 },
{ STATE_REPOMD, "tags", STATE_TAGS, 0 },
{ STATE_REPOMD, "data", STATE_DATA, 0 },
-
- { STATE_TAGS, "content", STATE_CONTENT, 1 },
+
+ { STATE_TAGS, "repo", STATE_REPO, 1 },
+ { STATE_TAGS, "content", STATE_CONTENT, 1 },
{ STATE_TAGS, "distro", STATE_DISTRO, 1 },
/* this tag is only valid in suseinfo.xml for now */
{ STATE_TAGS, "updates", STATE_UPDATES, 1 },
{ STATE_DATA, "location", STATE_LOCATION, 0 },
- { STATE_DATA, "checksum", STATE_CHECKSUM, 1 },
+ { STATE_DATA, "checksum", STATE_CHECKSUM, 1 },
{ STATE_DATA, "timestamp", STATE_TIMESTAMP, 1 },
- { STATE_DATA, "open-checksum", STATE_OPENCHECKSUM, 1 },
+ { STATE_DATA, "open-checksum", STATE_OPENCHECKSUM, 1 },
+ { STATE_DATA, "size", STATE_SIZE, 1 },
{ NUMSTATES }
};
struct parsedata {
+ int ret;
int depth;
enum state state;
int statedepth;
Pool *pool;
Repo *repo;
Repodata *data;
-
+
XML_Parser *parser;
struct stateswitch *swtab[NUMSTATES];
enum state sbtab[NUMSTATES];
/* repo data handle */
Id rdhandle;
- const char *tmpattr;
+ Id chksumtype;
};
/*
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
switch(pd->state)
{
- case STATE_START: break;
case STATE_REPOMD:
{
const char *updstr;
updstr = find_attr("updates", atts);
if (updstr)
{
- char *value = strdup(updstr);
+ char *value = solv_strdup(updstr);
char *fvalue = value; /* save the first */
while (value)
{
if (*p)
*p++ = 0;
if (*value)
- repo_add_poolstr_array(pd->repo, SOLVID_META, REPOSITORY_UPDATES, value);
+ repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_UPDATES, value);
value = p;
}
free(fvalue);
}
- break;
- }
- case STATE_SUSEINFO: break;
- case STATE_EXPIRE: break;
- case STATE_KEYWORDS: break;
- case STATE_KEYWORD: break;
- case STATE_CONTENT: break;
- case STATE_REVISION: break;
+ break;
+ }
case STATE_DISTRO:
{
/* this is extra metadata about the product this repository
was designed for */
const char *cpeid = find_attr("cpeid", atts);
pd->rphandle = repodata_new_handle(pd->data);
- /* set the cpeid for the product
+ /* set the cpeid for the product
the label is set in the content of the tag */
if (cpeid)
repodata_set_poolstr(pd->data, pd->rphandle, REPOSITORY_PRODUCT_CPEID, cpeid);
was designed for */
const char *cpeid = find_attr("cpeid", atts);
pd->ruhandle = repodata_new_handle(pd->data);
- /* set the cpeid for the product
+ /* set the cpeid for the product
the label is set in the content of the tag */
if (cpeid)
repodata_set_poolstr(pd->data, pd->ruhandle, REPOSITORY_PRODUCT_CPEID, cpeid);
const char *href = find_attr("href", atts);
if (href)
repodata_set_str(pd->data, pd->rdhandle, REPOSITORY_REPOMD_LOCATION, href);
+ break;
}
case STATE_CHECKSUM:
case STATE_OPENCHECKSUM:
- pd->tmpattr= find_attr("type", atts);
- break;
+ {
+ const char *type= 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");
+ break;
+ }
default:
break;
}
pd->statedepth--;
switch (pd->state)
{
- case STATE_START: break;
- case STATE_REPOMD:
+ case STATE_REPOMD:
if (pd->timestamp > 0)
repodata_set_num(pd->data, SOLVID_META, REPOSITORY_TIMESTAMP, pd->timestamp);
break;
repodata_add_flexarray(pd->data, SOLVID_META, REPOSITORY_REPOMD, pd->rdhandle);
pd->rdhandle = 0;
break;
- case STATE_LOCATION: break;
case STATE_CHECKSUM:
case STATE_OPENCHECKSUM:
- {
- int l;
- Id type;
- if (!strcasecmp(pd->tmpattr, "sha") || !strcasecmp(pd->tmpattr, "sha1"))
- l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
- else if (!strcasecmp(pd->tmpattr, "sha256"))
- l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256;
- else if (!strcasecmp(pd->tmpattr, "md5"))
- l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
- else
- {
- fprintf(stderr, "Unknown checksum type: %d: %s\n", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), pd->tmpattr);
- exit(1);
- }
- if (strlen(pd->content) != l)
- {
- fprintf(stderr, "Invalid checksum length: %d: for %s\n", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), pd->tmpattr);
- exit(1);
- }
- repodata_set_checksum(pd->data, pd->rdhandle, pd->state == STATE_CHECKSUM ? REPOSITORY_REPOMD_CHECKSUM : REPOSITORY_REPOMD_OPENCHECKSUM, type, pd->content);
- break;
- }
+ 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));
+ else
+ repodata_set_checksum(pd->data, pd->rdhandle, pd->state == STATE_CHECKSUM ? REPOSITORY_REPOMD_CHECKSUM : REPOSITORY_REPOMD_OPENCHECKSUM, pd->chksumtype, pd->content);
+ break;
case STATE_TIMESTAMP:
{
/* repomd.xml content and suseinfo.xml keywords are equivalent */
case STATE_CONTENT:
case STATE_KEYWORD:
- if (pd->content)
+ if (*pd->content)
repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_KEYWORDS, pd->content);
break;
case STATE_REVISION:
- if (pd->content)
- repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_REVISION, pd->content);
+ if (*pd->content)
+ repodata_set_str(pd->data, SOLVID_META, REPOSITORY_REVISION, pd->content);
break;
case STATE_DISTRO:
/* distro tag is used in repomd.xml to say the product this repo is
made for */
- if (pd->content)
+ if (*pd->content)
repodata_set_str(pd->data, pd->rphandle, REPOSITORY_PRODUCT_LABEL, pd->content);
repodata_add_flexarray(pd->data, SOLVID_META, REPOSITORY_DISTROS, pd->rphandle);
break;
case STATE_UPDATES:
- /* distro tag is used in suseinfo.xml to say the repo updates a product
+ /* 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)
+ if (*pd->content)
repodata_set_str(pd->data, pd->ruhandle, REPOSITORY_PRODUCT_LABEL, pd->content);
repodata_add_flexarray(pd->data, SOLVID_META, REPOSITORY_UPDATES, pd->ruhandle);
break;
- case STATE_SUSEINFO: break;
- case STATE_KEYWORDS: break;
- case NUMSTATES: break;
+ case STATE_REPO:
+ if (*pd->content)
+ repodata_add_poolstr_array(pd->data, SOLVID_META, REPOSITORY_REPOID, pd->content);
+ break;
+ case STATE_SIZE:
+ if (*pd->content)
+ repodata_set_num(pd->data, pd->rdhandle, REPOSITORY_REPOMD_SIZE, strtoull(pd->content, 0, 10));
+ break;
default:
break;
}
pd->state = pd->sbtab[pd->state];
pd->docontent = 0;
-
+
return;
}
#define BUFF_SIZE 8192
-void
+int
repo_add_repomdxml(Repo *repo, FILE *fp, int flags)
{
Pool *pool = repo->pool;
char buf[BUFF_SIZE];
int i, l;
struct stateswitch *sw;
+ XML_Parser parser;
- if (!(flags & REPO_REUSE_REPODATA))
- data = repo_add_repodata(repo, 0);
- else
- data = repo_last_repodata(repo);
+ data = repo_add_repodata(repo, flags);
memset(&pd, 0, sizeof(pd));
pd.timestamp = 0;
pd.content = malloc(256);
pd.acontent = 256;
pd.lcontent = 0;
- XML_Parser parser = XML_ParserCreate(NULL);
+ parser = XML_ParserCreate(NULL);
XML_SetUserData(parser, &pd);
pd.parser = &parser;
XML_SetElementHandler(parser, startElement, endElement);
l = fread(buf, 1, sizeof(buf), fp);
if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
{
- pool_debug(pool, SAT_FATAL, "repo_repomdxml: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
- exit(1);
+ 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;
repodata_internalize(data);
free(pd.content);
+ return pd.ret;
}
/* EOF */