X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=ext%2Frepo_products.c;h=f7a36e11912b968b1b1bc0bdf2b9b25b9edfddb9;hb=3ef3b1fc2683e955702472e838ff02bf2f68954a;hp=cf76050ff0d148cf311b27d8c55cc64773de310c;hpb=5b0d7883a182851bee1f5d67164d747ba00e4d6d;p=platform%2Fupstream%2Flibsolv.git diff --git a/ext/repo_products.c b/ext/repo_products.c index cf76050..f7a36e1 100644 --- a/ext/repo_products.c +++ b/ext/repo_products.c @@ -11,9 +11,13 @@ * for further information */ +#define _GNU_SOURCE +#define _XOPEN_SOURCE +#include #include #include #include +#include #include #include #include @@ -31,34 +35,36 @@ #include "tools_util.h" #include "repo_content.h" #include "repo_zyppdb.h" +#include "repo_products.h" #include "repo_releasefile_products.h" -//#define DUMPOUT 0 - enum state { - STATE_START, // 0 - STATE_PRODUCT, // 1 - STATE_VENDOR, // 2 - STATE_NAME, // 3 - STATE_VERSION, // 4 - STATE_RELEASE, // 5 - STATE_ARCH, // 6 - STATE_SUMMARY, // 7 + STATE_START, + STATE_PRODUCT, + STATE_VENDOR, + STATE_NAME, + STATE_VERSION, + STATE_RELEASE, + STATE_ARCH, + STATE_SUMMARY, STATE_SHORTSUMMARY, - STATE_DESCRIPTION, // 8 - STATE_UPDATEREPOKEY, // 9 should go away - STATE_CPEID, // 9 - STATE_URLS, // 10 - STATE_URL, // 11 - STATE_RUNTIMECONFIG, // 12 - STATE_LINGUAS, // 13 - STATE_LANG, // 14 - STATE_REGISTER, // 15 - STATE_TARGET, // 16 - STATE_REGRELEASE, // 18 - STATE_PRODUCTLINE, // 19 - NUMSTATES // 0 + STATE_DESCRIPTION, + STATE_UPDATEREPOKEY, + STATE_CPEID, + STATE_URLS, + STATE_URL, + STATE_RUNTIMECONFIG, + STATE_LINGUAS, + STATE_LANG, + STATE_REGISTER, + STATE_TARGET, + STATE_REGRELEASE, + STATE_PRODUCTLINE, + STATE_REGUPDATES, + STATE_REGUPDREPO, + STATE_ENDOFLIFE, + NUMSTATES }; struct stateswitch { @@ -86,10 +92,13 @@ static struct stateswitch stateswitches[] = { { STATE_PRODUCT, "linguas", STATE_LINGUAS, 0 }, { STATE_PRODUCT, "updaterepokey", STATE_UPDATEREPOKEY, 1 }, { STATE_PRODUCT, "cpeid", STATE_CPEID, 1 }, + { STATE_PRODUCT, "endoflife", STATE_ENDOFLIFE, 1 }, { STATE_URLS, "url", STATE_URL, 1 }, { STATE_LINGUAS, "lang", STATE_LANG, 0 }, { STATE_REGISTER, "target", STATE_TARGET, 1 }, { STATE_REGISTER, "release", STATE_REGRELEASE, 1 }, + { STATE_REGISTER, "updates", STATE_REGUPDATES, 0 }, + { STATE_REGUPDATES, "repository", STATE_REGUPDREPO, 0 }, { NUMSTATES } }; @@ -109,12 +118,13 @@ struct parsedata { struct stateswitch *swtab[NUMSTATES]; enum state sbtab[NUMSTATES]; + struct joindata jd; const char *tmplang; const char *tmpvers; const char *tmprel; - const char *tmpurltype; + Id urltype; unsigned int ctime; @@ -124,8 +134,6 @@ struct parsedata { ino_t baseproduct; ino_t currentproduct; int productscheme; - - Id langcache[ID_NUM_INTERNAL]; }; @@ -134,40 +142,45 @@ struct parsedata { * find value for xml attribute * I: txt, name of attribute * I: atts, list of key/value attributes - * I: dup, strdup it * O: pointer to value of matching key, or NULL * */ static inline const char * -find_attr(const char *txt, const char **atts, int dup) +find_attr(const char *txt, const char **atts) { for (; *atts; atts += 2) { if (!strcmp(*atts, txt)) - return dup ? solv_strdup(atts[1]) : atts[1]; + return atts[1]; } return 0; } - -/* - * create localized tag - */ - -static Id -langtag(struct parsedata *pd, Id tag, const char *language) +static time_t +datestr2timestamp(const char *date) { - if (language && !language[0]) - language = 0; - if (!language || tag >= ID_NUM_INTERNAL) - return pool_id2langid(pd->repo->pool, tag, language, 1); - if (!pd->langcache[tag]) - pd->langcache[tag] = pool_id2langid(pd->repo->pool, tag, language, 1); - return pd->langcache[tag]; + const char *p; + struct tm tm; + + if (!date || !*date) + return 0; + for (p = date; *p >= '0' && *p <= '9'; p++) + ; + if (!*p) + return atoi(date); + memset(&tm, 0, sizeof(tm)); + p = strptime(date, "%F%T", &tm); + if (!p) + { + memset(&tm, 0, sizeof(tm)); + p = strptime(date, "%F", &tm); + if (!p || *p) + return 0; + } + return timegm(&tm); } - /* * XML callback: startElement */ @@ -181,7 +194,7 @@ startElement(void *userData, const char *name, const char **atts) struct stateswitch *sw; #if 0 - fprintf(stderr, "start: [%d]%s\n", pd->state, name); + fprintf(stderr, "start: [%d]%s\n", pd->state, name); #endif if (pd->depth != pd->statedepth) { @@ -219,7 +232,7 @@ startElement(void *userData, const char *name, const char **atts) case STATE_PRODUCT: /* parse 'schemeversion' and store in global variable */ { - const char * scheme = find_attr("schemeversion", atts, 0); + const char * scheme = find_attr("schemeversion", atts); pd->productscheme = (scheme && *scheme) ? atoi(scheme) : -1; } if (!s) @@ -231,14 +244,23 @@ startElement(void *userData, const char *name, const char **atts) /* ... */ case STATE_SUMMARY: - pd->tmplang = find_attr("lang", atts, 1); - break; case STATE_DESCRIPTION: - pd->tmplang = find_attr("lang", atts, 1); + pd->tmplang = join_dup(&pd->jd, find_attr("lang", atts)); break; case STATE_URL: - pd->tmpurltype = find_attr("name", atts, 1); + pd->urltype = pool_str2id(pd->pool, find_attr("name", atts), 1); break; + case STATE_REGUPDREPO: + { + const char *repoid = find_attr("repoid", atts); + if (repoid && *repoid) + { + Id h = repodata_new_handle(pd->data); + repodata_set_str(pd->data, h, PRODUCT_UPDATES_REPOID, repoid); + repodata_add_flexarray(pd->data, pd->handle, PRODUCT_UPDATES, h); + } + break; + } default: break; } @@ -252,7 +274,7 @@ endElement(void *userData, const char *name) Solvable *s = pd->solvable; #if 0 - fprintf(stderr, "end: [%d]%s\n", pd->state, name); + fprintf(stderr, "end: [%d]%s\n", pd->state, name); #endif if (pd->depth != pd->statedepth) { @@ -283,7 +305,7 @@ endElement(void *userData, const char *name) if (pd->tmprel) { if (pd->tmpvers) - s->evr = makeevr(pd->pool, join2(pd->tmpvers, "-", pd->tmprel)); + s->evr = makeevr(pd->pool, join2(&pd->jd, pd->tmpvers, "-", pd->tmprel)); else { fprintf(stderr, "Seen but no \n"); @@ -305,7 +327,7 @@ endElement(void *userData, const char *name) s->vendor = pool_str2id(pd->pool, pd->content, 1); break; case STATE_NAME: - s->name = pool_str2id(pd->pool, join2("product", ":", pd->content), 1); + s->name = pool_str2id(pd->pool, join2(&pd->jd, "product", ":", pd->content), 1); break; case STATE_VERSION: pd->tmpvers = solv_strdup(pd->content); @@ -323,23 +345,20 @@ endElement(void *userData, const char *name) /** obsolete **/ break; case STATE_SUMMARY: - repodata_set_str(pd->data, pd->handle, langtag(pd, SOLVABLE_SUMMARY, pd->tmplang), pd->content); - pd->tmplang = solv_free((void *)pd->tmplang); + repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), pd->content); break; case STATE_SHORTSUMMARY: repodata_set_str(pd->data, pd->handle, PRODUCT_SHORTLABEL, pd->content); break; case STATE_DESCRIPTION: - repodata_set_str(pd->data, pd->handle, langtag(pd, SOLVABLE_DESCRIPTION, pd->tmplang), pd->content ); - pd->tmplang = solv_free((void *)pd->tmplang); + repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), pd->content); break; case STATE_URL: - if (pd->tmpurltype) + if (pd->urltype) { repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); - repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, pool_str2id(pd->pool, pd->tmpurltype, 1)); + repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, pd->urltype); } - pd->tmpurltype = solv_free((void *)pd->tmpurltype); break; case STATE_TARGET: repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_TARGET, pd->content); @@ -348,8 +367,17 @@ endElement(void *userData, const char *name) repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_RELEASE, pd->content); break; case STATE_CPEID: - if (pd->content) + if (*pd->content) repodata_set_str(pd->data, pd->handle, SOLVABLE_CPEID, pd->content); + break; + case STATE_ENDOFLIFE: + if (*pd->content) + { + time_t t = datestr2timestamp(pd->content); + if (t) + repodata_set_num(pd->data, pd->handle, PRODUCT_ENDOFLIFE, (unsigned long long)t); + } + break; default: break; } @@ -408,7 +436,7 @@ add_code11_product(struct parsedata *pd, FILE *fp) else { pd->currentproduct = pd->baseproduct + 1; /* make it != baseproduct if stat fails */ - perror("fstat"); + pool_error(pd->pool, 0, "fstat: %s", strerror(errno)); pd->ctime = 0; } @@ -423,8 +451,12 @@ add_code11_product(struct parsedata *pd, FILE *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)); - pool_debug(pd->pool, SOLV_ERROR, "skipping this product\n"); XML_ParserFree(parser); + if (pd->solvable) + { + repo_free_solvable(pd->repo, pd->solvable - pd->pool->solvables, 1); + pd->solvable = 0; + } return; } if (l == 0) @@ -434,7 +466,7 @@ add_code11_product(struct parsedata *pd, FILE *fp) } -void +int repo_add_code11_products(Repo *repo, const char *dirpath, int flags) { Repodata *data; @@ -460,6 +492,8 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags) pd.sbtab[sw->to] = sw->from; } + if (flags & REPO_USE_ROOTDIR) + dirpath = pool_prepend_rootdir(repo->pool, dirpath); dir = opendir(dirpath); if (dir) { @@ -468,7 +502,7 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags) char *fullpath; /* check for /baseproduct on code11 and remember its target inode */ - if (stat(join2(dirpath, "/", "baseproduct"), &st) == 0) /* follow symlink */ + if (stat(join2(&pd.jd, dirpath, "/", "baseproduct"), &st) == 0) /* follow symlink */ pd.baseproduct = st.st_ino; else pd.baseproduct = 0; @@ -479,11 +513,11 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags) FILE *fp; if (len <= 5 || strcmp(entry->d_name + len - 5, ".prod") != 0) continue; - fullpath = join2(dirpath, "/", entry->d_name); + fullpath = join2(&pd.jd, dirpath, "/", entry->d_name); fp = fopen(fullpath, "r"); if (!fp) { - perror(fullpath); + pool_error(repo->pool, 0, "%s: %s", fullpath, strerror(errno)); continue; } pd.filename = fullpath; @@ -493,12 +527,14 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags) } closedir(dir); } - solv_free((void *)pd.tmplang); solv_free(pd.content); - join_freemem(); + join_freemem(&pd.jd); + if (flags & REPO_USE_ROOTDIR) + solv_free((char *)dirpath); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); + return 0; } @@ -516,51 +552,60 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags) /* Oh joy! Three parsers for the price of one! */ -void -repo_add_products(Repo *repo, const char *proddir, const char *root, int flags) +int +repo_add_products(Repo *repo, const char *proddir, int flags) { const char *fullpath; DIR *dir; - dir = opendir(proddir); - if (dir) + if (proddir) { - /* assume code11 stype products */ - closedir(dir); - repo_add_code11_products(repo, proddir, flags); - return; + dir = opendir(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(repo->pool, proddir) : proddir); + if (dir) + { + /* assume code11 stype products */ + closedir(dir); + return repo_add_code11_products(repo, proddir, flags); + } } - /* code11 didn't work, try old zyppdb */ - fullpath = root ? join2(root, "", "/var/lib/zypp/db/products") : "/var/lib/zypp/db/products"; + /* code11 didn't work, try old code10 zyppdb */ + fullpath = "/var/lib/zypp/db/products"; + if (flags & REPO_USE_ROOTDIR) + fullpath = pool_prepend_rootdir_tmp(repo->pool, fullpath); dir = opendir(fullpath); if (dir) { closedir(dir); /* assume code10 style products */ - repo_add_zyppdb_products(repo, fullpath, flags); - join_freemem(); - return; + return repo_add_zyppdb_products(repo, "/var/lib/zypp/db/products", flags); } - /* code11 didn't work, try -release files parsing */ - fullpath = root ? join2(root, "", "/etc") : "/etc"; + /* code10/11 didn't work, try -release files parsing */ + fullpath = "/etc"; + if (flags & REPO_USE_ROOTDIR) + fullpath = pool_prepend_rootdir_tmp(repo->pool, fullpath); dir = opendir(fullpath); if (dir) { closedir(dir); - repo_add_releasefile_products(repo, fullpath, flags); - join_freemem(); - return; + return repo_add_releasefile_products(repo, "/etc", flags); } - /* no luck. print an error message in case the root argument is wrong */ - perror(fullpath); - join_freemem(); + /* no luck. check if the rootdir exists */ + fullpath = pool_get_rootdir(repo->pool); + if (fullpath && *fullpath) + { + dir = opendir(fullpath); + if (!dir) + return pool_error(repo->pool, -1, "%s: %s", fullpath, strerror(errno)); + closedir(dir); + } /* the least we can do... */ if (!(flags & REPO_NO_INTERNALIZE) && (flags & REPO_REUSE_REPODATA) != 0) repodata_internalize(repo_last_repodata(repo)); + return 0; } /* EOF */