attribute store files. Good night.
(Like so:
% addstore bla.solv ding.attr dong.attr > bla2.solv
% dumpsolv bla2.solv
repo refers to 2 attribute stores:
ding.attr has 4 keys
authors
group
keywords
license
dong.attr has 4 keys
authors
keywords
license
...
)
#define TYPE_ATTR_LOCALIDS 10
#define TYPE_COUNT_NAMED 11
-#define TYPE_ATTR_TYPE_MAX 11
+#define TYPE_COUNTED 12
+#define TYPE_ATTR_TYPE_MAX 12
//-----------------------------------------------
}
void
-repo_add_attrstore (Repo *repo, Attrstore *s)
+repo_add_attrstore (Repo *repo, Attrstore *s, const char *name)
{
unsigned i;
Repodata *data;
+ /* If this is meant to be the embedded attributes, make sure we don't
+ have them already. */
+ if (!name)
+ {
+ for (i = 0; i < repo->nrepodata; i++)
+ if (repo->repodata[i].name == 0)
+ break;
+ if (i != repo->nrepodata)
+ {
+ pool_debug (repo->pool, SAT_FATAL, "embedded attribs added twice\n");
+ exit (1);
+ }
+ }
repo->nrepodata++;
repo->repodata = xrealloc (repo->repodata, repo->nrepodata * sizeof (*data));
data = repo->repodata + repo->nrepodata - 1;
memset (data, 0, sizeof (*data));
data->s = s;
data->nkeys = s->nkeys;
- if (s->nkeys)
+ /* Don't store the first key, it's {0,0,0}. */
+ data->nkeys--;
+ if (data->nkeys)
{
data->keys = xmalloc (data->nkeys * sizeof (data->keys[0]));
for (i = 0; i < data->nkeys; i++)
{
- data->keys[i].name = s->keys[i].name;
- data->keys[i].type = s->keys[i].type;
+ data->keys[i].name = s->keys[i + 1].name;
+ data->keys[i].type = s->keys[i + 1].type;
}
qsort (data->keys, data->nkeys, sizeof (data->keys[0]), key_cmp);
}
+ if (name)
+ data->name = strdup (name);
}
// EOF
/* The attribute store itself. */
Attrstore *s;
/* A filename where to find this attribute store, or where to store
- it. May be NULL, in which case we can't load it on demand or store
- into it. */
+ it. May be "", in which case we can't load it on demand or store
+ into it. It may also be NULL for at most one of the repodata per
+ repo, in which case these are the embedded attributes. */
const char *name;
/* The SHA1 checksum of the file. */
unsigned char checksum[20];
extern Offset repo_reserve_ids(Repo *repo, Offset olddeps, int num);
extern Offset repo_fix_legacy(Repo *repo, Offset provides, Offset supplements);
-extern void repo_add_attrstore (Repo *repo, Attrstore *s);
+extern void repo_add_attrstore (Repo *repo, Attrstore *s, const char *name);
static inline const char *repo_name(const Repo *repo)
{
}
}
+static void
+read_str (FILE *fp, char **inbuf, unsigned *len)
+{
+ unsigned char *buf = (unsigned char*)*inbuf;
+ if (!buf)
+ {
+ buf = xmalloc (1024);
+ *len = 1024;
+ }
+ int c;
+ unsigned ofs = 0;
+ while((c = getc (fp)) != 0)
+ {
+ if (c == EOF)
+ {
+ pool_debug (mypool, SAT_FATAL, "unexpected EOF\n");
+ exit (1);
+ }
+ /* Plus 1 as we also want to add the 0. */
+ if (ofs + 1 >= *len)
+ {
+ *len += 256;
+ /* Don't realloc on the inbuf, it might be on the stack. */
+ if (buf == (unsigned char*)*inbuf)
+ {
+ buf = xmalloc (*len);
+ memcpy (buf, *inbuf, *len - 256);
+ }
+ else
+ buf = xrealloc (buf, *len);
+ }
+ buf[ofs++] = c;
+ }
+ buf[ofs++] = 0;
+ *inbuf = (char*)buf;
+}
static void
skip_item (FILE *fp, unsigned type, Id *idmap, unsigned numid, unsigned numrel)
}
}
break;
+ case TYPE_COUNTED:
+ {
+ unsigned count = read_id (fp, 0);
+ unsigned t = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
+ while (count--)
+ skip_item (fp, t, idmap, numid, numrel);
+ }
+ break;
case TYPE_ATTR_CHUNK:
read_id(fp, 0);
/* Fallthrough. */
}
}
+static int
+key_cmp (const void *pa, const void *pb)
+{
+ struct key { Id name; unsigned type; };
+ struct key *a = (struct key*)pa;
+ struct key *b = (struct key*)pb;
+ return a->name - b->name;
+}
+
+static void
+parse_repodata (FILE *fp, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
+{
+ unsigned count = read_id (fp, 0);
+
+ while (count--)
+ {
+ Repodata *data;
+ read_id (fp, numid); /* no name */
+ unsigned type = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
+ if (type != TYPE_COUNT_NAMED)
+ {
+ skip_item (fp, type, idmap, numid, numrel);
+ continue;
+ }
+ unsigned c = read_id (fp, 0);
+ if (c == 0)
+ continue;
+ if (c != 2)
+ {
+ pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
+ exit (1);
+ }
+ read_id (fp, numid); /* no name */
+ if (read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_STR)
+ {
+ pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
+ exit (1);
+ }
+ char buf[1024];
+ unsigned len = sizeof (buf);
+ char *filename = buf;
+ read_str (fp, &filename, &len);
+
+ read_id (fp, numid); /* no name */
+ if (read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_COUNTED)
+ {
+ pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
+ exit (1);
+ }
+
+ unsigned nkeys = read_id (fp, 0);
+ if ((nkeys & 1) != 0
+ || read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_ID)
+ {
+ pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
+ exit (1);
+ }
+ nkeys >>= 1;
+
+ repo->nrepodata++;
+ data = xrealloc (repo->repodata, repo->nrepodata * sizeof (*data));
+ repo->repodata = data;
+ data += repo->nrepodata - 1;
+ memset (data, 0, sizeof (*data));
+ data->nkeys = nkeys;
+ if (data->nkeys)
+ {
+ unsigned i;
+ data->keys = xmalloc (data->nkeys * sizeof (data->keys[0]));
+ for (i = 0; i < data->nkeys; i++)
+ {
+ data->keys[i].name = idmap[read_id (fp, numid)];
+ data->keys[i].type = read_id (fp, 0);
+ }
+ qsort (data->keys, data->nkeys, sizeof (data->keys[0]), key_cmp);
+ }
+ data->name = strdup (filename);
+
+ if (filename != buf)
+ xfree (filename);
+ }
+}
+
/*-----------------------------------------------------------------*/
struct key {
unsigned type = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
if (type == TYPE_COUNT_NAMED
&& !strcmp (id2str (pool, name), "repodata"))
- skip_item (fp, type, idmap, numid, numrel);
+ parse_repodata (fp, idmap, numid, numrel, repo);
else
skip_item (fp, type, idmap, numid, numrel);
}
attr_store_pack (embedded_store);
/* If we have any attributes we also have pages. */
read_or_setup_pages (fp, embedded_store);
- repo_add_attrstore (repo, embedded_store);
+ /* The NULL name here means embedded attributes. */
+ repo_add_attrstore (repo, embedded_store, NULL);
}
xfree(idmap);
xfree(schemata);
ADD_EXECUTABLE( dumpattr ${dumpattr_REPOS} )
TARGET_LINK_LIBRARIES( dumpattr satsolver)
+ADD_EXECUTABLE( addstore addstore.c repo_write.c )
+TARGET_LINK_LIBRARIES( addstore satsolver )
+
install(TARGETS dumpattr
mergesolv
dumpsolv
helix2solv
rpmmd2solv
rpmdb2solv
+ addstore
DESTINATION ${BIN_INSTALL_DIR} )
install(PROGRAMS repo2solv.sh DESTINATION ${BIN_INSTALL_DIR} )
--- /dev/null
+/*
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "pool.h"
+#include "repo_solv.h"
+#include "repo_write.h"
+#include "attr_store.h"
+#include "attr_store_p.h"
+
+int
+main(int argc, char **argv)
+{
+ Repo *repo;
+ Pool *pool;
+ int i;
+ FILE *fp;
+
+ if (argc == 1)
+ {
+ printf ("%s repo.solv one.attr [more.attr ...] > out.solv\n", argv[0]);
+ exit (1);
+ }
+ if ((fp = fopen (argv[1], "r")) == 0)
+ {
+ perror (argv[1]);
+ exit (1);
+ }
+ pool = pool_create ();
+ repo = repo_create (pool, argv[1]);
+ repo_add_solv (repo, fp);
+ fclose (fp);
+ for (i = 2; i < argc; i++)
+ {
+ if ((fp = fopen (argv[i], "r")) == 0)
+ {
+ perror (argv[1]);
+ exit (1);
+ }
+ Attrstore *s = attr_store_read (fp, pool);
+ fclose (fp);
+ /* XXX We should probably use the basename here.
+ And calculate the SHA1 sum of the file and store it. */
+ repo_add_attrstore (repo, s, argv[i]);
+ }
+ repo_write(repo, stdout);
+ pool_free(pool);
+ exit(0);
+}
}
}
+static void
+dump_repodata (Repo *repo)
+{
+ unsigned i;
+ Repodata *d;
+ if (repo->nrepodata == 0)
+ return;
+ printf ("repo refers to %d attribute stores:\n", repo->nrepodata);
+ for (i = 0, d = repo->repodata; i < repo->nrepodata; i++, d++)
+ {
+ unsigned j;
+ printf ("%s has %d keys", d->name ? d->name : "**EMBED**", d->nkeys);
+ for (j = 0; j < d->nkeys; j++)
+ printf ("\n %s", id2str (repo->pool, d->keys[j].name));
+ printf ("\n");
+ }
+ printf ("\n");
+}
+
static void
printids(Repo *repo, char *kind, Offset ido)
{
pool = pool_create();
repo = repo_create(pool, argc != 1 ? argv[1] : "<stdin>");
repo_add_solv(repo, stdin);
+ dump_repodata (repo);
printf("repo contains %d solvables\n", repo->nsolvables);
for (i = repo->start, n = 1; i < repo->end; i++)
{
}
}
+static void
+write_str(FILE *fp, const char *str)
+{
+ if (fputs (str, fp) == EOF
+ || putc (0, fp) == EOF)
+ {
+ perror("write error");
+ exit(1);
+ }
+}
/*
* Array of Ids
Id lastschema[256];
Id lastschemakey[256];
+ /* For the info block. */
+ Id repodata_id, hello_id;
+
+ repodata_id = str2id (pool, "repodata", 1);
+ hello_id = str2id (pool, "hello", 1);
+
nsolvables = 0;
idarraydata = repo->idarraydata;
needid = (NeedId *)xcalloc(pool->ss.nstrings + pool->nrels, sizeof(*needid));
+ needid[repodata_id].need++;
+ needid[hello_id].need++;
+ for (i = 0; i < repo->nrepodata; i++)
+ {
+ int j;
+ for (j = 0; j < repo->repodata[i].nkeys; j++)
+ needid[repo->repodata[i].keys[j].name].need++;
+ }
+
memset(idsizes, 0, sizeof(idsizes));
for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
/* write file header */
write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V');
- write_u32(fp, SOLV_VERSION_2);
+ write_u32(fp, SOLV_VERSION_3);
/* write counts */
write_u32(fp, nstrings);
write_u32(fp, nsolvables);
write_u32(fp, nkeys);
write_u32(fp, nschemata);
- write_u32(fp, 0); /* no info block */
+ write_u32(fp, 2); /* Info block. */
solv_flags = 0;
solv_flags |= SOLV_FLAG_PREFIX_POOL;
#if 0
while (*sp++)
;
}
-
+
+ /*
+ * write info block
+ */
+ write_id (fp, needid[hello_id].need);
+ write_id (fp, TYPE_COUNT_NAMED);
+ write_id (fp, 1);
+ write_id (fp, 0); //name
+ write_id (fp, TYPE_STR);
+ write_str (fp, "doll");
+
+ write_id (fp, needid[repodata_id].need);
+ write_id (fp, TYPE_COUNT_NAMED);
+ write_id (fp, repo->nrepodata);
+ for (i = 0; i < repo->nrepodata; i++)
+ {
+ int j;
+ write_id (fp, 0); /* no name, isn't important here */
+ write_id (fp, TYPE_COUNT_NAMED);
+ /* Don't emit the embedded attributes. */
+ if (repo->repodata[i].name == 0)
+ {
+ write_id (fp, 0); /* count */
+ continue;
+ }
+ write_id (fp, 2); /* 2 items, the filename and the keys */
+ /* 1 filename */
+ write_id (fp, 0); /* no name */
+ write_id (fp, TYPE_STR);
+ write_str (fp, repo->repodata[i].name);
+
+ /* 2 keys */
+ write_id (fp, 0); /* no name */
+ write_id (fp, TYPE_COUNTED);
+ write_id (fp, repo->repodata[i].nkeys * 2);
+ write_id (fp, TYPE_ID);
+ for (j = 0; j < repo->repodata[i].nkeys; j++)
+ {
+ write_id (fp, needid[repo->repodata[i].keys[j].name].need);
+ write_id (fp, repo->repodata[i].keys[j].type);
+ }
+ }
+
#if 0
if (1)
{