2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
19 #include "tools_util.h"
20 #include "repo_rpmmd.h"
45 /* resobject attributes */
60 /* Novell/SUSE extended attributes */
73 STATE_CATEGORY, /* pattern and patches */
82 STATE_DISTNAME, // obsolete
83 STATE_DISTEDITION, // obsolete
93 /* rpm-md dependencies inside the
109 STATE_OBSOLETESENTRY,
110 STATE_CONFLICTSENTRY,
111 STATE_RECOMMENDSENTRY,
112 STATE_SUPPLEMENTSENTRY,
130 static struct stateswitch stateswitches[] = {
131 /** fake tag used to enclose 2 different xml files in one **/
132 { STATE_START, "rpmmd", STATE_START, 0 },
134 /** tags for different package data, we just ignore the tag **/
135 { STATE_START, "metadata", STATE_START, 0 },
136 { STATE_START, "otherdata", STATE_START, 0 },
137 { STATE_START, "diskusagedata", STATE_START, 0 },
138 { STATE_START, "susedata", STATE_START, 0 },
140 { STATE_START, "product", STATE_SOLVABLE, 0 },
141 { STATE_START, "pattern", STATE_SOLVABLE, 0 },
142 { STATE_START, "patch", STATE_SOLVABLE, 0 },
143 { STATE_START, "package", STATE_SOLVABLE, 0 },
145 { STATE_SOLVABLE, "name", STATE_NAME, 1 },
146 { STATE_SOLVABLE, "arch", STATE_ARCH, 1 },
147 { STATE_SOLVABLE, "version", STATE_VERSION, 0 },
149 // package attributes rpm-md
150 { STATE_SOLVABLE, "location", STATE_LOCATION, 0 },
151 { STATE_SOLVABLE, "checksum", STATE_CHECKSUM, 1 },
153 /* resobject attributes */
155 { STATE_SOLVABLE, "summary", STATE_SUMMARY, 1 },
156 { STATE_SOLVABLE, "description", STATE_DESCRIPTION, 1 },
157 { STATE_SOLVABLE, "distribution", STATE_DISTRIBUTION, 1 },
158 { STATE_SOLVABLE, "url", STATE_URL, 1 },
159 { STATE_SOLVABLE, "packager", STATE_PACKAGER, 1 },
160 //{ STATE_SOLVABLE, "???", STATE_INSNOTIFY, 1 },
161 //{ STATE_SOLVABLE, "??", STATE_DELNOTIFY, 1 },
162 { STATE_SOLVABLE, "vendor", STATE_VENDOR, 1 },
163 { STATE_SOLVABLE, "size", STATE_SIZE, 0 },
164 { STATE_SOLVABLE, "archive-size", STATE_DOWNLOADSIZE, 1 },
165 { STATE_SOLVABLE, "install-time", STATE_INSTALLTIME, 1 },
166 { STATE_SOLVABLE, "install-only", STATE_INSTALLONLY, 1 },
167 { STATE_SOLVABLE, "time", STATE_TIME, 0 },
169 /* extended Novell/SUSE attributes (suseinfo.xml) */
170 { STATE_SOLVABLE, "eula", STATE_EULA, 1 },
171 { STATE_SOLVABLE, "diskusage", STATE_DISKUSAGE, 0 },
172 { STATE_DISKUSAGE, "dirs", STATE_DIRS, 0 },
173 { STATE_DIRS, "dir", STATE_DIR, 0 },
176 { STATE_SOLVABLE, "script", STATE_SCRIPT, 1 },
177 { STATE_SOLVABLE, "icon", STATE_ICON, 1 },
178 { STATE_SOLVABLE, "uservisible", STATE_USERVISIBLE, 1 },
179 { STATE_SOLVABLE, "category", STATE_CATEGORY, 1 },
180 { STATE_SOLVABLE, "default", STATE_DEFAULT, 1 },
181 { STATE_SOLVABLE, "install-time", STATE_INSTALL_TIME, 1 },
183 /* product attributes */
184 /* note the product type is an attribute */
185 { STATE_SOLVABLE, "release-notes-url", STATE_RELNOTESURL, 1 },
186 { STATE_SOLVABLE, "update-url", STATE_UPDATEURL, 1 },
187 { STATE_SOLVABLE, "optional-url", STATE_OPTIONALURL, 1 },
188 { STATE_SOLVABLE, "flag", STATE_FLAG, 1 },
189 { STATE_SOLVABLE, "flavor", STATE_FLAVOR, 1 },
190 { STATE_SOLVABLE, "references", STATE_REFERENCES, 1 },
192 { STATE_SOLVABLE, "rpm:vendor", STATE_VENDOR, 1 },
193 { STATE_SOLVABLE, "rpm:group", STATE_RPM_GROUP, 1 },
194 { STATE_SOLVABLE, "rpm:license", STATE_RPM_LICENSE, 1 },
196 /* rpm-md dependencies */
197 { STATE_SOLVABLE, "rpm:provides", STATE_PROVIDES, 0 },
198 { STATE_SOLVABLE, "rpm:requires", STATE_REQUIRES, 0 },
199 { STATE_SOLVABLE, "rpm:obsoletes", STATE_OBSOLETES, 0 },
200 { STATE_SOLVABLE, "rpm:conflicts", STATE_CONFLICTS, 0 },
201 { STATE_SOLVABLE, "rpm:recommends", STATE_RECOMMENDS , 0 },
202 { STATE_SOLVABLE, "rpm:supplements", STATE_SUPPLEMENTS, 0 },
203 { STATE_SOLVABLE, "rpm:suggests", STATE_SUGGESTS, 0 },
204 { STATE_SOLVABLE, "rpm:enhances", STATE_ENHANCES, 0 },
205 { STATE_SOLVABLE, "rpm:freshens", STATE_FRESHENS, 0 },
206 { STATE_SOLVABLE, "rpm:sourcerpm", STATE_SOURCERPM, 1 },
207 { STATE_SOLVABLE, "rpm:header-range", STATE_HEADERRANGE, 0 },
208 { STATE_SOLVABLE, "file", STATE_FILE, 1 },
210 { STATE_PROVIDES, "rpm:entry", STATE_PROVIDESENTRY, 0 },
211 { STATE_REQUIRES, "rpm:entry", STATE_REQUIRESENTRY, 0 },
212 { STATE_OBSOLETES, "rpm:entry", STATE_OBSOLETESENTRY, 0 },
213 { STATE_CONFLICTS, "rpm:entry", STATE_CONFLICTSENTRY, 0 },
214 { STATE_RECOMMENDS, "rpm:entry", STATE_RECOMMENDSENTRY, 0 },
215 { STATE_SUPPLEMENTS, "rpm:entry", STATE_SUPPLEMENTSENTRY, 0 },
216 { STATE_SUGGESTS, "rpm:entry", STATE_SUGGESTSENTRY, 0 },
217 { STATE_ENHANCES, "rpm:entry", STATE_ENHANCESENTRY, 0 },
218 { STATE_FRESHENS, "rpm:entry", STATE_FRESHENSENTRY, 0 },
223 /* maxmum initial size of
224 the checksum cache */
225 #define MAX_CSCACHE 32768
226 #define CSREALLOC_STEP 1024
229 struct parsedata_common common;
240 struct stateswitch *swtab[NUMSTATES];
241 enum state sbtab[NUMSTATES];
242 /* temporal to store attribute tag language */
245 // used to store tmp attributes
246 // while the tag ends
251 Id (*dirs)[3]; // dirid, size, nfiles
253 Id langcache[ID_NUM_INTERNAL];
254 /** system language */
255 const char *language;
257 /** Hash to maps checksums to solv */
259 /** Cache of known checksums to solvable id */
261 /* the current longest index in the table */
266 langtag(struct parsedata *pd, Id tag, const char *language)
268 if (language && !language[0])
270 if (!language || tag >= ID_NUM_INTERNAL)
271 return pool_id2langid(pd->common.repo->pool, tag, language, 1);
272 return pool_id2langid(pd->common.repo->pool, tag, language, 1);
273 if (!pd->langcache[tag])
274 pd->langcache[tag] = pool_id2langid(pd->common.repo->pool, tag, language, 1);
275 return pd->langcache[tag];
279 id3_cmp (const void *v1, const void *v2)
283 return i1[0] - i2[0];
287 commit_diskusage (struct parsedata *pd, unsigned handle)
290 Dirpool *dp = &pd->data->dirpool;
291 /* Now sort in dirid order. This ensures that parents come before
294 qsort(pd->dirs, pd->ndirs, sizeof (pd->dirs[0]), id3_cmp);
295 /* Substract leaf numbers from all parents to make the numbers
296 non-cumulative. This must be done post-order (i.e. all leafs
297 adjusted before parents). We ensure this by starting at the end of
298 the array moving to the start, hence seeing leafs before parents. */
299 for (i = pd->ndirs; i--;)
301 unsigned p = dirpool_parent(dp, pd->dirs[i][0]);
303 for (; p; p = dirpool_parent(dp, p))
306 if (pd->dirs[j][0] == p)
310 if (pd->dirs[j][1] < pd->dirs[i][1])
313 pd->dirs[j][1] -= pd->dirs[i][1];
314 if (pd->dirs[j][2] < pd->dirs[i][2])
317 pd->dirs[j][2] -= pd->dirs[i][2];
320 /* Haven't found this parent in the list, look further if
321 we maybe find the parents parent. */
328 unsigned slen = sizeof (sbuf);
329 for (i = 0; i < pd->ndirs; i++)
331 dir2str (attr, pd->dirs[i][0], &buf, &slen);
332 fprintf (stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf);
337 for (i = 0; i < pd->ndirs; i++)
338 if (pd->dirs[i][1] || pd->dirs[i][2])
340 repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
348 * parse 'epoch', 'ver' and 'rel', return evr Id
353 makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts)
355 const char *e, *v, *r, *v2;
360 for (; *atts; atts += 2)
362 if (!strcmp(*atts, "epoch"))
364 else if (!strcmp(*atts, "ver"))
366 else if (!strcmp(*atts, "rel"))
369 if (e && !strcmp(e, "0"))
373 for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++)
375 if (v2 > v && *v2 == ':')
385 if (l > pd->acontent)
387 pd->content = sat_realloc(pd->content, l + 256);
388 pd->acontent = l + 256;
412 fprintf(stderr, "evr: %s\n", pd->content);
414 return str2id(pool, pd->content, 1);
420 * find value for xml attribute
421 * I: txt, name of attribute
422 * I: atts, list of key/value attributes
423 * O: pointer to value of matching key, or NULL
427 static inline const char *
428 find_attr(const char *txt, const char **atts)
430 for (; *atts; atts += 2)
432 if (!strcmp(*atts, txt))
440 * dependency relations
443 static char *flagtab[] = {
455 * parse attributes to reldep Id
460 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts, int isreq)
463 const char *n, *f, *k;
467 marker = isreq ? -SOLVABLE_PREREQMARKER : 0;
468 for (a = atts; *a; a += 2)
470 if (!strcmp(*a, "name"))
472 else if (!strcmp(*a, "flags"))
474 else if (!strcmp(*a, "kind"))
476 else if (isreq && !strcmp(*a, "pre") && a[1][0] == '1')
477 marker = SOLVABLE_PREREQMARKER;
481 if (k && !strcmp(k, "package"))
485 int l = strlen(k) + 1 + strlen(n) + 1;
486 if (l > pd->acontent)
488 pd->content = sat_realloc(pd->content, l + 256);
489 pd->acontent = l + 256;
491 sprintf(pd->content, "%s:%s", k, n);
492 name = str2id(pool, pd->content, 1);
495 name = str2id(pool, (char *)n, 1);
498 Id evr = makeevr_atts(pool, pd, atts);
500 for (flags = 0; flags < 6; flags++)
501 if (!strcmp(f, flagtab[flags]))
503 flags = flags < 6 ? flags + 1 : 0;
504 id = rel2id(pool, name, evr, flags, 1);
509 fprintf(stderr, "new dep %s%s%s\n", id2str(pool, d), id2rel(pool, d), id2evr(pool, d));
511 return repo_addid_dep(pd->common.repo, olddeps, id, marker);
516 * set_desciption_author
521 set_desciption_author(Repodata *data, Id handle, char *str)
527 for (aut = str; (aut = strchr(aut, '\n')) != 0; aut++)
528 if (!strncmp(aut, "\nAuthors:\n--------\n", 19))
532 /* oh my, found SUSE special author section */
535 while (l > 0 && str[l - 1] == '\n')
538 repodata_set_str(data, handle, SOLVABLE_DESCRIPTION, str);
540 aut = str; /* copy over */
541 while (*p == ' ' || *p == '\n')
554 while (aut != str && aut[-1] == '\n')
558 repodata_set_str(data, handle, SOLVABLE_AUTHORS, str);
561 repodata_set_str(data, handle, SOLVABLE_DESCRIPTION, str);
571 set_sourcerpm(Repodata *data, Solvable *s, Id handle, char *sourcerpm)
573 const char *p, *sevr, *sarch, *name, *evr;
576 p = strrchr(sourcerpm, '.');
577 if (!p || strcmp(p, ".rpm") != 0)
580 while (p > sourcerpm && *p != '.')
582 if (*p != '.' || p == sourcerpm)
585 while (p > sourcerpm && *p != '-')
587 if (*p != '-' || p == sourcerpm)
590 while (p > sourcerpm && *p != '-')
592 if (*p != '-' || p == sourcerpm)
595 pool = s->repo->pool;
596 name = id2str(pool, s->name);
597 evr = id2str(pool, s->evr);
598 if (!strcmp(sarch, "src.rpm"))
599 repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_SRC);
600 else if (!strcmp(sarch, "nosrc.rpm"))
601 repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_NOSRC);
603 repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, strn2id(pool, sarch, strlen(sarch) - 4, 1));
604 if (!strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0)
605 repodata_set_void(data, handle, SOLVABLE_SOURCEEVR);
607 repodata_set_id(data, handle, SOLVABLE_SOURCEEVR, strn2id(pool, sevr, sarch - sevr - 1, 1));
608 if (!strncmp(sourcerpm, name, sevr - sourcerpm - 1) && name[sevr - sourcerpm -
610 repodata_set_void(data, handle, SOLVABLE_SOURCENAME);
612 repodata_set_id(data, handle, SOLVABLE_SOURCENAME, strn2id(pool, sourcerpm, sevr - sourcerpm - 1, 1));
615 /*-----------------------------------------------*/
625 startElement(void *userData, const char *name, const char **atts)
627 //fprintf(stderr,"+tag: %s\n", name);
628 struct parsedata *pd = userData;
629 Pool *pool = pd->common.pool;
630 Solvable *s = pd->solvable;
631 struct stateswitch *sw;
633 Id handle = pd->handle;
635 // fprintf(stderr, "into %s, from %d, depth %d, statedepth %d\n", name, pd->state, pd->depth, pd->statedepth);
637 if (pd->depth != pd->statedepth)
643 if (pd->state == STATE_START && !strcmp(name, "patterns"))
645 if (pd->state == STATE_START && !strcmp(name, "metadata"))
647 if (pd->state == STATE_SOLVABLE && !strcmp(name, "format"))
651 for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)
652 if (!strcmp(sw->ename, name))
654 if (sw->from != pd->state)
657 fprintf(stderr, "into unknown: %s\n", name);
662 pd->docontent = sw->docontent;
663 pd->statedepth = pd->depth;
670 if (name[2] == 't' && name[3] == 't')
671 pd->kind = "pattern";
672 else if (name[1] == 'r')
673 pd->kind = "product";
674 else if (name[2] == 't' && name[3] == 'c')
677 /* to support extension metadata files like others.xml which
678 have the following structure:
680 <otherdata xmlns="http://linux.duke.edu/metadata/other"
682 <package pkgid="b78f8664cd90efe42e09a345e272997ef1b53c18"
683 name="zaptel-kmp-default"
684 arch="i586"><version epoch="0"
685 ver="1.2.10_2.6.22_rc4_git6_2" rel="70"/>
688 we need to check if the pkgid is there and if it matches
689 an already seen package, that means we don't need to create
690 a new solvable but just append the attributes to the existing
694 if ( (pkgid = find_attr("pkgid", atts)) != NULL )
697 /*const char *name = find_attr("name", atts);*/
698 // look at the checksum cache
699 Id index = stringpool_str2id (&pd->cspool, pkgid, 1 /* create it */);
700 if ( index < pd->ncscache )
702 Id solvid = pd->cscache[index-1];
706 Solvable *s = pool_id2solvable(pool, solvid);
707 /* we found the already defined package */
710 /*fprintf(stderr, "package found %s-%s.\n", name, find_attr("arch", atts));*/
715 fprintf(stderr, "error, the repository specifies extra information about package with checksum '%s', which does not exist in the repository.\n", pkgid);
721 /* this is a new package */
722 pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->common.repo));
724 repodata_extend(pd->data, pd->solvable - pool->solvables);
726 pd->handle = repodata_get_handle(pd->data, (pd->solvable - pool->solvables) - pd->data->start);
728 fprintf(stderr, "package #%d\n", pd->solvable - pool->solvables);
733 s->evr = makeevr_atts(pool, pd, atts);
738 case STATE_PROVIDESENTRY:
739 s->provides = adddep(pool, pd, s->provides, atts, 0);
744 case STATE_REQUIRESENTRY:
745 s->requires = adddep(pool, pd, s->requires, atts, 1);
747 case STATE_OBSOLETES:
750 case STATE_OBSOLETESENTRY:
751 s->obsoletes = adddep(pool, pd, s->obsoletes, atts, 0);
753 case STATE_CONFLICTS:
756 case STATE_CONFLICTSENTRY:
757 s->conflicts = adddep(pool, pd, s->conflicts, atts, 0);
759 case STATE_RECOMMENDS:
762 case STATE_RECOMMENDSENTRY:
763 s->recommends = adddep(pool, pd, s->recommends, atts, 0);
765 case STATE_SUPPLEMENTS:
768 case STATE_SUPPLEMENTSENTRY:
769 s->supplements = adddep(pool, pd, s->supplements, atts, 0);
774 case STATE_SUGGESTSENTRY:
775 s->suggests = adddep(pool, pd, s->suggests, atts, 0);
780 case STATE_ENHANCESENTRY:
781 s->enhances = adddep(pool, pd, s->enhances, atts, 0);
786 case STATE_FRESHENSENTRY:
787 pd->freshens = adddep(pool, pd, pd->freshens, atts, 0);
790 case STATE_DESCRIPTION:
791 pd->tmplang = find_attr("lang", atts);
794 str = find_attr("href", atts);
797 const char *str2 = strrchr(str, '/');
800 char *str3 = strdup(str);
801 str3[str2 - str] = 0;
802 repodata_set_poolstr(pd->data, handle, SOLVABLE_MEDIADIR, str3);
804 repodata_set_str(pd->data, handle, SOLVABLE_MEDIAFILE, str2 + 1);
807 repodata_set_str(pd->data, handle, SOLVABLE_MEDIAFILE, str);
811 pd->tmpattr = find_attr("type", atts);
816 str = find_attr("build", atts);
817 if (str && (t = atoi(str)) != 0)
818 repodata_set_num(pd->data, handle, SOLVABLE_BUILDTIME, t);
824 str = find_attr("installed", atts);
825 if (str && (k = atoi(str)) != 0)
826 repodata_set_num(pd->data, handle, SOLVABLE_INSTALLSIZE, (k + 1023) / 1024);
827 /* XXX the "package" attribute gives the size of the rpm file,
828 i.e. the download size. Except on packman, there it seems to be
829 something else entirely, it has a value near to the other two
830 values, as if the rpm is uncompressed. */
831 str = find_attr("package", atts);
832 if (str && (k = atoi(str)) != 0)
833 repodata_set_num(pd->data, handle, SOLVABLE_DOWNLOADSIZE, (k + 1023) / 1024);
836 case STATE_HEADERRANGE:
839 str = find_attr("end", atts);
840 if (str && (end = atoi(str)) != 0)
841 repodata_set_num(pd->data, handle, SOLVABLE_HEADEREND, end);
846 <dir name="/" size="56" count="11"/>
847 <dir name="usr/" size="56" count="11"/>
848 <dir name="usr/bin/" size="38" count="10"/>
849 <dir name="usr/share/" size="18" count="1"/>
850 <dir name="usr/share/doc/" size="18" count="1"/>
854 case STATE_DISKUSAGE:
856 /* Really, do nothing, wat for <dir> tag */
861 long filesz = 0, filenum = 0;
863 if ( (str = find_attr("name", atts)) )
865 dirid = repodata_str2dir(pd->data, str, 1);
869 fprintf( stderr, "<dir .../> tag without 'name' attribute, atts = %p, *atts = %p\n", atts, *atts);
872 if ( (str = find_attr("size", atts)) )
874 filesz = strtol (str, 0, 0);
876 if ( (str = find_attr("count", atts)) )
878 filenum = strtol (str, 0, 0);
880 pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
881 pd->dirs[pd->ndirs][0] = dirid;
882 pd->dirs[pd->ndirs][1] = filesz;
883 pd->dirs[pd->ndirs][2] = filenum;
900 endElement(void *userData, const char *name)
902 //fprintf(stderr,"-tag: %s\n", name);
903 struct parsedata *pd = userData;
904 Pool *pool = pd->common.pool;
905 Solvable *s = pd->solvable;
906 Repo *repo = pd->common.repo;
907 Id handle = pd->handle;
911 if (pd->depth != pd->statedepth)
914 // printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
918 /* ignore patterns & metadata */
919 if (pd->state == STATE_START && !strcmp(name, "patterns"))
921 if (pd->state == STATE_START && !strcmp(name, "metadata"))
923 if (pd->state == STATE_SOLVABLE && !strcmp(name, "format"))
934 s->arch = ARCH_NOARCH;
936 s->evr = ID_EMPTY; /* some patterns have this */
937 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
938 s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
939 s->supplements = repo_fix_legacy(repo, s->provides, s->supplements, pd->freshens);
945 s->name = str2id(pool, join2( pd->kind, ":", pd->content), 1);
947 s->name = str2id(pool, pd->content, 1);
950 s->arch = str2id(pool, pd->content, 1);
953 s->vendor = str2id(pool, pd->content, 1);
955 case STATE_RPM_GROUP:
956 repodata_set_poolstr(pd->data, handle, SOLVABLE_GROUP, pd->content);
958 case STATE_RPM_LICENSE:
959 repodata_set_poolstr(pd->data, handle, SOLVABLE_LICENSE, pd->content);
965 if (!strcasecmp (pd->tmpattr, "sha") || !strcasecmp (pd->tmpattr, "sha1"))
966 l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
967 else if (!strcasecmp (pd->tmpattr, "md5"))
968 l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
971 fprintf(stderr, "Unknown checksum type: %d: %s\n", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), pd->tmpattr);
974 if (strlen(pd->content) != l)
976 fprintf(stderr, "Invalid checksum length: %d: for %s\n", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), pd->tmpattr);
979 repodata_set_checksum(pd->data, handle, SOLVABLE_CHECKSUM, type, pd->content);
980 /* we save the checksum to solvable id relationship for extended
982 Id index = stringpool_str2id (&pd->cspool, pd->content, 1 /* create it */);
983 if ( index >= pd->ncscache )
985 /** realloc for this index plus CSREALLOC_STEP*/
986 pd->cscache = (Id *) sat_zextend(pd->cscache, pd->ncscache, index - pd->ncscache +1, sizeof(Id), 255);
987 /** fill the realloced part with 0s */
989 pd->ncscache = index +1;
992 /* add the checksum to the cache */
993 pd->cscache[index-1] = s - pool->solvables;
999 id = str2id(pool, pd->content, 1);
1000 s->provides = repo_addid_dep(repo, s->provides, id, SOLVABLE_FILEMARKER);
1002 if ((p = strrchr(pd->content, '/')) != 0)
1005 id = repodata_str2dir(pd->data, pd->content, 1);
1013 id = repodata_str2dir(pd->data, "/", 1);
1014 repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, id, p);
1018 repodata_set_str(pd->data, handle, SOLVABLE_SUMMARY, pd->content);
1020 case STATE_DESCRIPTION:
1022 set_desciption_author(pd->data, handle, pd->content);
1024 case STATE_DISTRIBUTION:
1025 repodata_set_poolstr(pd->data, handle, SOLVABLE_DISTRIBUTION, pd->content);
1029 repodata_set_str(pd->data, handle, SOLVABLE_URL, pd->content);
1031 case STATE_PACKAGER:
1033 repodata_set_poolstr(pd->data, handle, SOLVABLE_PACKAGER, pd->content);
1035 case STATE_SOURCERPM:
1036 set_sourcerpm(pd->data, s, handle, pd->content);
1038 case STATE_RELNOTESURL:
1040 repodata_set_poolstr(pd->data, handle, PRODUCT_RELNOTESURL, pd->content);
1042 case STATE_UPDATEURL:
1044 repodata_set_poolstr(pd->data, handle, PRODUCT_EXTRAURLS, pd->content);
1046 case STATE_OPTIONALURL:
1048 repodata_set_poolstr(pd->data, handle, PRODUCT_OPTIONALURLS, pd->content);
1052 repodata_set_poolstr(pd->data, handle, PRODUCT_FLAGS, pd->content);
1056 repodata_set_str(pd->data, handle, PRODUCT_FLAVOR, pd->content);
1058 case STATE_REFERENCES:
1060 repodata_set_str(pd->data, handle, PRODUCT_REFERENCES, pd->content);
1064 repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_EULA, pd->language), pd->content);
1066 case STATE_DISKUSAGE:
1068 commit_diskusage (pd, pd->handle);
1073 pd->state = pd->sbtab[pd->state];
1075 // fprintf(stderr, "back from known %d %d %d\n", pd->state, pd->depth, pd->statedepth);
1086 characterData(void *userData, const XML_Char *s, int len)
1088 struct parsedata *pd = userData;
1094 l = pd->lcontent + len + 1;
1095 if (l > pd->acontent)
1097 pd->content = sat_realloc(pd->content, l + 256);
1098 pd->acontent = l + 256;
1100 c = pd->content + pd->lcontent;
1101 pd->lcontent += len;
1108 /*-----------------------------------------------*/
1111 #define BUFF_SIZE 8192
1115 * parse rpm-md metadata (primary, others)
1120 repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags)
1122 Pool *pool = repo->pool;
1123 struct parsedata pd;
1124 char buf[BUFF_SIZE];
1126 struct stateswitch *sw;
1128 memset(&pd, 0, sizeof(pd));
1129 for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++)
1131 if (!pd.swtab[sw->from])
1132 pd.swtab[sw->from] = sw;
1133 pd.sbtab[sw->to] = sw->from;
1135 pd.common.pool = pool;
1136 pd.common.repo = repo;
1138 pd.data = repo_add_repodata(repo, 0);
1140 pd.content = sat_malloc(256);
1146 pd.language = language;
1148 /* initialize the string pool where we will store
1149 the package checksums we know about, to get an Id
1150 we can use in a cache */
1151 stringpool_init_empty(&pd.cspool);
1152 pd.cscache = (Id *) calloc(MAX_CSCACHE, sizeof(Id));
1153 pd.ncscache = MAX_CSCACHE;
1155 XML_Parser parser = XML_ParserCreate(NULL);
1156 XML_SetUserData(parser, &pd);
1157 pd.parser = &parser;
1158 XML_SetElementHandler(parser, startElement, endElement);
1159 XML_SetCharacterDataHandler(parser, characterData);
1162 l = fread(buf, 1, sizeof(buf), fp);
1163 if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR)
1165 fprintf(stderr, "repo_rpmmd: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser));
1171 XML_ParserFree(parser);
1174 repodata_internalize(pd.data);
1175 sat_free(pd.content);