/*
* repo_write.c
- *
+ *
* Write Repo data out to a file in solv format
- *
- * See doc/README.format for a description
+ *
+ * See doc/README.format for a description
* of the binary file format
- *
+ *
*/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <errno.h>
#include "pool.h"
#include "util.h"
* increment need Id
* idarray: array of Ids, ID_NULL terminated
* needid: array of Id->NeedId
- *
+ *
* return size of array (including trailing zero)
- *
+ *
*/
static void
/*
- *
+ *
*/
static int
*/
static void
-write_u32(FILE *fp, unsigned int x)
+write_u32(Repodata *data, unsigned int x)
{
+ FILE *fp = data->fp;
+ if (data->error)
+ return;
if (putc(x >> 24, fp) == EOF ||
putc(x >> 16, fp) == EOF ||
putc(x >> 8, fp) == EOF ||
putc(x, fp) == EOF)
{
- perror("write error u32");
- exit(1);
+ data->error = pool_error(data->repo->pool, -1, "write error u32: %s", strerror(errno));
}
}
*/
static void
-write_u8(FILE *fp, unsigned int x)
+write_u8(Repodata *data, unsigned int x)
{
- if (putc(x, fp) == EOF)
+ if (data->error)
+ return;
+ if (putc(x, data->fp) == EOF)
{
- perror("write error u8");
- exit(1);
+ data->error = pool_error(data->repo->pool, -1, "write error u8: %s", strerror(errno));
}
}
*/
static void
-write_blob(FILE *fp, void *data, int len)
+write_blob(Repodata *data, void *blob, int len)
{
- if (len && fwrite(data, len, 1, fp) != 1)
+ if (data->error)
+ return;
+ if (len && fwrite(blob, len, 1, data->fp) != 1)
{
- perror("write error blob");
- exit(1);
+ data->error = pool_error(data->repo->pool, -1, "write error blob: %s", strerror(errno));
}
}
*/
static void
-write_id(FILE *fp, Id x)
+write_id(Repodata *data, Id x)
{
+ FILE *fp = data->fp;
+ if (data->error)
+ return;
if (x >= (1 << 14))
{
if (x >= (1 << 28))
putc((x >> 7) | 128, fp);
if (putc(x & 127, fp) == EOF)
{
- perror("write error id");
- exit(1);
+ data->error = pool_error(data->repo->pool, -1, "write error id: %s", strerror(errno));
}
}
static inline void
-write_id_eof(FILE *fp, Id x, int eof)
+write_id_eof(Repodata *data, Id x, int eof)
{
if (x >= 64)
x = (x & 63) | ((x & ~63) << 1);
- write_id(fp, x | (eof ? 0 : 64));
+ write_id(data, x | (eof ? 0 : 64));
}
static inline void
-write_str(FILE *fp, const char *str)
+write_str(Repodata *data, const char *str)
{
- if (fputs(str, fp) == EOF || putc(0, fp) == EOF)
+ if (data->error)
+ return;
+ if (fputs(str, data->fp) == EOF || putc(0, data->fp) == EOF)
{
- perror("write error str");
- exit(1);
+ data->error = pool_error(data->repo->pool, -1, "write error str: %s", strerror(errno));
}
}
*/
static void
-write_idarray(FILE *fp, Pool *pool, NeedId *needid, Id *ids)
+write_idarray(Repodata *data, Pool *pool, NeedId *needid, Id *ids)
{
Id id;
if (!ids)
return;
if (!*ids)
{
- write_u8(fp, 0);
+ write_u8(data, 0);
return;
}
for (;;)
id = (id & 63) | ((id & ~63) << 1);
if (!*ids)
{
- write_id(fp, id);
+ write_id(data, id);
return;
}
- write_id(fp, id | 64);
+ write_id(data, id | 64);
}
}
#if 0
static void
-write_idarray_sort(FILE *fp, Pool *pool, NeedId *needid, Id *ids, Id marker)
+write_idarray_sort(Repodata *data, Pool *pool, NeedId *needid, Id *ids, Id marker)
{
int len, i;
Id lids[64], *sids;
return;
if (!*ids)
{
- write_u8(fp, 0);
+ write_u8(data, 0);
return;
}
for (len = 0; len < 64 && ids[len]; len++)
we might want to skip writing them out. */
if (id >= 64)
id = (id & 63) | ((id & ~63) << 1);
- write_id(fp, id | 64);
+ write_id(data, id | 64);
}
id = sids[i];
if (id == marker)
id = id - old + 1;
if (id >= 64)
id = (id & 63) | ((id & ~63) << 1);
- write_id(fp, id);
+ write_id(data, id);
if (sids != lids)
solv_free(sids);
}
Id lastlen;
int doingsolvables; /* working on solvables data */
+ int filelistmode;
};
#define NEEDED_BLOCK 1023
{
unsigned int x = (unsigned int)sx;
unsigned char *dp;
+
xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
dp = xd->buf + xd->len;
}
static inline void
-data_addideof(struct extdata *xd, Id x, int eof)
+data_addideof(struct extdata *xd, Id sx, int eof)
{
- if (x >= 64)
- x = (x & 63) | ((x & ~63) << 1);
- data_addid(xd, (eof ? x: x | 64));
+ unsigned int x = (unsigned int)sx;
+ unsigned char *dp;
+
+ xd->buf = solv_extend(xd->buf, xd->len, 5, 1, EXTDATA_BLOCK);
+ dp = xd->buf + xd->len;
+
+ if (x >= (1 << 13))
+ {
+ if (x >= (1 << 27))
+ *dp++ = (x >> 27) | 128;
+ if (x >= (1 << 20))
+ *dp++ = (x >> 20) | 128;
+ *dp++ = (x >> 13) | 128;
+ }
+ if (x >= (1 << 6))
+ *dp++ = (x >> 6) | 128;
+ *dp++ = eof ? (x & 63) : (x & 63) | 64;
+ xd->len = dp - xd->buf;
}
-static void
+static inline int
+data_addideof_len(Id sx)
+{
+ unsigned int x = (unsigned int)sx;
+ if (x >= (1 << 13))
+ {
+ if (x >= (1 << 27))
+ return 5;
+ return x >= (1 << 20) ? 4 : 3;
+ }
+ return x >= (1 << 6) ? 2 : 1;
+}
+
+static void
data_addid64(struct extdata *xd, unsigned int x, unsigned int hx)
{
if (hx)
- {
+ {
if (hx > 7)
{
data_addid(xd, (Id)(hx >> 3));
- xd->buf[xd->len - 1] |= 128;
+ xd->buf[xd->len - 1] |= 128;
hx &= 7;
}
data_addid(xd, (Id)(x | 0x80000000));
- xd->buf[xd->len - 5] = (x >> 28) | (hx << 4) | 128;
+ xd->buf[xd->len - 5] = (x >> 28) | (hx << 4) | 128;
}
- else
+ else
data_addid(xd, (Id)x);
}
}
/* XXX If difference is zero we have multiple equal elements,
we might want to skip writing them out. */
- if (id >= 64)
- id = (id & 63) | ((id & ~63) << 1);
- data_addid(xd, id | 64);
+ data_addideof(xd, id, 0);
}
id = sids[i];
if (id == marker)
id = 0;
else
id = id - old + 1;
- if (id >= 64)
- id = (id & 63) | ((id & ~63) << 1);
- data_addid(xd, id);
+ data_addideof(xd, id, 1);
if (sids != lids)
solv_free(sids);
}
{
if (cbdata->oldschema)
{
- fprintf(stderr, "nested structs not yet implemented\n");
- exit(1);
+ cbdata->target->error = pool_error(cbdata->repo->pool, -1, "nested fixarray structs not yet implemented");
+ return SEARCH_NEXT_KEY;
}
cbdata->oldschema = cbdata->schema;
cbdata->oldsp = cbdata->sp;
rm = cbdata->keymap[cbdata->keymapstart[data->repodataid] + (key - data->keys)];
if (!rm)
return SEARCH_NEXT_KEY; /* we do not want this one */
-
+
if (cbdata->target->keys[rm].storage == KEY_STORAGE_VERTICAL_OFFSET)
{
xd = cbdata->extdata + rm; /* vertical buffer */
case REPOKEY_TYPE_SHA1:
data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA1);
break;
+ case REPOKEY_TYPE_SHA224:
+ data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA224);
+ break;
case REPOKEY_TYPE_SHA256:
data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA256);
break;
+ case REPOKEY_TYPE_SHA384:
+ data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA384);
+ break;
+ case REPOKEY_TYPE_SHA512:
+ data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA512);
+ break;
case REPOKEY_TYPE_U32:
u32 = kv->num;
v[0] = u32 >> 24;
if (cbdata->owndirpool)
id = putinowndirpool(cbdata, data, &data->dirpool, id);
id = cbdata->dirused[id];
+ if (cbdata->filelistmode > 0)
+ {
+ xd->len += data_addideof_len(id) + strlen(kv->str) + 1;
+ break;
+ }
data_addideof(xd, id, kv->eof);
data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1);
+ if (cbdata->filelistmode < 0)
+ return 0;
break;
case REPOKEY_TYPE_FIXARRAY:
if (kv->eof == 0)
}
break;
default:
- fprintf(stderr, "unknown type for %d: %d\n", key->name, key->type);
- exit(1);
+ cbdata->target->error = pool_error(cbdata->repo->pool, -1, "unknown type for %d: %d\n", key->name, key->type);
+ break;
}
if (cbdata->target->keys[rm].storage == KEY_STORAGE_VERTICAL_OFFSET && kv->eof)
{
}
static void
-write_compressed_page(FILE *fp, unsigned char *page, int len)
+write_compressed_page(Repodata *data, unsigned char *page, int len)
{
int clen;
unsigned char cpage[REPOPAGE_BLOBSIZE];
clen = repopagestore_compress_page(page, len, cpage, len - 1);
if (!clen)
{
- write_u32(fp, len * 2);
- write_blob(fp, page, len);
+ write_u32(data, len * 2);
+ write_blob(data, page, len);
}
else
{
- write_u32(fp, clen * 2 + 1);
- write_blob(fp, cpage, clen);
+ write_u32(data, clen * 2 + 1);
+ write_blob(data, cpage, clen);
}
}
SOLVABLE_EULA,
SOLVABLE_DISKUSAGE,
SOLVABLE_FILELIST,
+ SOLVABLE_CHECKSUM,
+ DELTA_CHECKSUM,
+ DELTA_SEQ_NUM,
+ SOLVABLE_PKGID,
+ SOLVABLE_HDRID,
+ SOLVABLE_LEADSIGID,
+ SOLVABLE_CHANGELOG_AUTHOR,
+ SOLVABLE_CHANGELOG_TEXT,
0
};
}
/*
+ * return true if the repodata contains the filelist (and just
+ * the filelist). The same code is used in the dataiterator. The way
+ * it is used is completely wrong, of course, as having the filelist
+ * key does not mean it is used for a specific solvable. Nevertheless
+ * it is better to have it than to write broken solv files.
+ */
+static inline int
+is_filelist_extension(Repodata *data)
+{
+ int j;
+ for (j = 1; j < data->nkeys; j++)
+ if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
+ return 0;
+ return 1;
+}
+
+
+static int
+write_compressed_extdata(Repodata *target, struct extdata *xd, unsigned char *vpage, int lpage)
+{
+ unsigned char *dp = xd->buf;
+ int l = xd->len;
+ while (l)
+ {
+ int ll = REPOPAGE_BLOBSIZE - lpage;
+ if (l < ll)
+ ll = l;
+ memcpy(vpage + lpage, dp, ll);
+ dp += ll;
+ lpage += ll;
+ l -= ll;
+ if (lpage == REPOPAGE_BLOBSIZE)
+ {
+ write_compressed_page(target, vpage, lpage);
+ lpage = 0;
+ }
+ }
+ return lpage;
+}
+
+/*
* Repo
*/
repo_write_filtered(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Queue *keyq)
{
Pool *pool = repo->pool;
- int i, j, n;
+ int i, j, n, lastfilelistn;
Solvable *s;
NeedId *needid;
int nstrings, nrels;
unsigned char *repodataused;
int anyrepodataused = 0;
int anysolvableused = 0;
-
+
struct cbdata cbdata;
int clonepool;
Repokey *key;
Id type_constantid = REPOKEY_TYPE_CONSTANTID;
- unsigned char *prefixcomp;
- unsigned int compsum;
- char *old_str;
-
memset(&cbdata, 0, sizeof(cbdata));
cbdata.repo = repo;
dirpool = 0;
dirpooldata = 0;
n = ID_NUM_INTERNAL;
+ lastfilelistn = 0;
FOR_REPODATAS(repo, i, data)
{
cbdata.keymapstart[i] = n;
idused = 1; /* dirs also use ids */
dirused = 1;
}
+ if (key->type == REPOKEY_TYPE_DIRSTRARRAY && key->name == SOLVABLE_FILELIST)
+ {
+ /* is this a file list extension */
+ if (is_filelist_extension(data))
+ {
+ /* hmm, we have a file list extension. Kill filelist of other repodata.
+ * XXX: this is wrong, as the extension does not need to cover all
+ * solvables of the other repodata */
+ if (lastfilelistn)
+ cbdata.keymap[lastfilelistn] = 0;
+ }
+ else
+ lastfilelistn = n;
+ }
}
if (idused)
{
{
data_addid(xd, repo->nsolvables); /* FLEXARRAY nentries */
cbdata.doingsolvables = 1;
+
+ /* check if we can do the special filelist memory optimization */
+ if (anyrepodataused)
+ {
+ for (i = 1; i < target.nkeys; i++)
+ if (target.keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET)
+ cbdata.filelistmode |= cbdata.filelistmode == 0 && target.keys[i].type == REPOKEY_TYPE_DIRSTRARRAY ? 1 : 2;
+ else if (target.keys[i].type == REPOKEY_TYPE_DIRSTRARRAY)
+ cbdata.filelistmode = 2;
+ if (cbdata.filelistmode != 1)
+ cbdata.filelistmode = 0;
+ }
+
for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++)
{
if (s->repo != repo)
/********************************************************************/
+ target.fp = fp;
+
/* write header */
/* write file header */
- write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V');
- write_u32(fp, SOLV_VERSION_8);
+ write_u32(&target, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V');
+ write_u32(&target, SOLV_VERSION_8);
/* write counts */
- write_u32(fp, nstrings);
- write_u32(fp, nrels);
- write_u32(fp, ndirmap);
- write_u32(fp, anysolvableused ? repo->nsolvables : 0);
- write_u32(fp, target.nkeys);
- write_u32(fp, target.nschemata);
+ write_u32(&target, nstrings);
+ write_u32(&target, nrels);
+ write_u32(&target, ndirmap);
+ write_u32(&target, anysolvableused ? repo->nsolvables : 0);
+ write_u32(&target, target.nkeys);
+ write_u32(&target, target.nschemata);
solv_flags = 0;
solv_flags |= SOLV_FLAG_PREFIX_POOL;
- write_u32(fp, solv_flags);
+ solv_flags |= SOLV_FLAG_SIZE_BYTES;
+ write_u32(&target, solv_flags);
- /*
- * calculate prefix encoding of the strings
- */
- prefixcomp = solv_malloc(nstrings);
- compsum = 0;
- old_str = "";
-
- prefixcomp[0] = 0;
- for (i = 1; i < nstrings; i++)
- {
- char *str = spool->stringspace + spool->strings[needid[i].map];
- int same;
- for (same = 0; same < 255; same++)
- if (!old_str[same] || old_str[same] != str[same])
- break;
- prefixcomp[i] = same;
- compsum += same;
- old_str = str;
- }
-
- /*
- * write strings
- */
- write_u32(fp, sizeid);
- /* we save compsum bytes but need 1 extra byte for every string */
- write_u32(fp, sizeid + (nstrings ? nstrings - 1 : 0) - compsum);
- if (sizeid + (nstrings ? nstrings - 1 : 0) != compsum)
+ if (nstrings)
{
+ /*
+ * calculate prefix encoding of the strings
+ */
+ unsigned char *prefixcomp = solv_malloc(nstrings);
+ unsigned int compsum = 0;
+ char *old_str = "";
+
+ prefixcomp[0] = 0;
for (i = 1; i < nstrings; i++)
{
char *str = spool->stringspace + spool->strings[needid[i].map];
- write_u8(fp, prefixcomp[i]);
- write_str(fp, str + prefixcomp[i]);
+ int same;
+ for (same = 0; same < 255; same++)
+ if (!old_str[same] || old_str[same] != str[same])
+ break;
+ prefixcomp[i] = same;
+ compsum += same;
+ old_str = str;
}
- }
- solv_free(prefixcomp);
-#if 0
- /* Build the prefix-encoding of the string pool. We need to know
- the size of that before writing it to the file, so we have to
- build a separate buffer for that. As it's temporarily possible
- that this actually is an expansion we can't easily reuse the
- stringspace for this. The max expansion per string is 1 byte,
- so it will fit into sizeid+nstrings bytes. */
- char *prefix = solv_malloc(sizeid + nstrings);
- char *pp = prefix;
- char *old_str = "";
- for (i = 1; i < nstrings; i++)
- {
- char *str = spool->stringspace + spool->strings[needid[i].map];
- int same;
- size_t len;
- for (same = 0; same < 255; same++)
- if (!old_str[same] || !str[same] || old_str[same] != str[same])
- break;
- *pp++ = same;
- len = strlen(str + same) + 1;
- memcpy(pp, str + same, len);
- pp += len;
- old_str = str;
- }
-
- /*
- * write strings
- */
- write_u32(fp, sizeid);
- write_u32(fp, pp - prefix);
- if (pp != prefix)
- {
- if (fwrite(prefix, pp - prefix, 1, fp) != 1)
+ /*
+ * write strings
+ */
+ write_u32(&target, sizeid);
+ /* we save compsum bytes but need 1 extra byte for every string */
+ write_u32(&target, sizeid + nstrings - 1 - compsum);
+ for (i = 1; i < nstrings; i++)
{
- perror("write error prefix");
- exit(1);
+ char *str = spool->stringspace + spool->strings[needid[i].map];
+ write_u8(&target, prefixcomp[i]);
+ write_str(&target, str + prefixcomp[i]);
}
+ solv_free(prefixcomp);
+ }
+ else
+ {
+ write_u32(&target, 0);
+ write_u32(&target, 0);
}
- solv_free(prefix);
-#endif
/*
* write RelDeps
for (i = 0; i < nrels; i++)
{
ran = pool->rels + (needid[reloff + i].map - reloff);
- write_id(fp, needid[ISRELDEP(ran->name) ? RELOFF(ran->name) : ran->name].need);
- write_id(fp, needid[ISRELDEP(ran->evr) ? RELOFF(ran->evr) : ran->evr].need);
- write_u8(fp, ran->flags);
+ write_id(&target, needid[ISRELDEP(ran->name) ? RELOFF(ran->name) : ran->name].need);
+ write_id(&target, needid[ISRELDEP(ran->evr) ? RELOFF(ran->evr) : ran->evr].need);
+ write_u8(&target, ran->flags);
}
/*
for (i = 2; i < ndirmap; i++)
{
if (dirmap[i] > 0)
- write_id(fp, dirmap[i]);
+ write_id(&target, dirmap[i]);
else
- write_id(fp, nstrings - dirmap[i]);
+ write_id(&target, nstrings - dirmap[i]);
}
solv_free(dirmap);
*/
for (i = 1; i < target.nkeys; i++)
{
- write_id(fp, needid[target.keys[i].name].need);
- write_id(fp, needid[target.keys[i].type].need);
+ write_id(&target, needid[target.keys[i].name].need);
+ write_id(&target, needid[target.keys[i].type].need);
if (target.keys[i].storage != KEY_STORAGE_VERTICAL_OFFSET)
{
if (target.keys[i].type == type_constantid)
- write_id(fp, needid[target.keys[i].size].need);
+ write_id(&target, needid[target.keys[i].size].need);
else
- write_id(fp, target.keys[i].size);
+ write_id(&target, target.keys[i].size);
}
else
- write_id(fp, cbdata.extdata[i].len);
- write_id(fp, target.keys[i].storage);
+ write_id(&target, cbdata.extdata[i].len);
+ write_id(&target, target.keys[i].storage);
}
/*
* write schemata
*/
- write_id(fp, target.schemadatalen); /* XXX -1? */
+ write_id(&target, target.schemadatalen); /* XXX -1? */
for (i = 1; i < target.nschemata; i++)
- write_idarray(fp, pool, 0, repodata_id2schema(&target, i));
+ write_idarray(&target, pool, 0, repodata_id2schema(&target, i));
/********************************************************************/
- write_id(fp, cbdata.maxdata);
- write_id(fp, cbdata.extdata[0].len);
+ write_id(&target, cbdata.maxdata);
+ write_id(&target, cbdata.extdata[0].len);
if (cbdata.extdata[0].len)
- write_blob(fp, cbdata.extdata[0].buf, cbdata.extdata[0].len);
+ write_blob(&target, cbdata.extdata[0].buf, cbdata.extdata[0].len);
solv_free(cbdata.extdata[0].buf);
/* do we have vertical data? */
if (i < target.nkeys)
{
/* yes, write it in pages */
- unsigned char *dp, vpage[REPOPAGE_BLOBSIZE];
- int l, ll, lpage = 0;
+ unsigned char vpage[REPOPAGE_BLOBSIZE];
+ int lpage = 0;
- write_u32(fp, REPOPAGE_BLOBSIZE);
+ write_u32(&target, REPOPAGE_BLOBSIZE);
for (i = 1; i < target.nkeys; i++)
+ if (cbdata.extdata[i].len)
+ {
+ if (cbdata.filelistmode)
+ break;
+ lpage = write_compressed_extdata(&target, cbdata.extdata + i, vpage, lpage);
+ }
+ if (cbdata.filelistmode && i < target.nkeys)
{
- if (!cbdata.extdata[i].len)
- continue;
- l = cbdata.extdata[i].len;
- dp = cbdata.extdata[i].buf;
- while (l)
+ /* ok, just this single extdata, which is a filelist */
+ xd = cbdata.extdata + i;
+ xd->len = 0;
+ cbdata.filelistmode = -1;
+ for (j = 0; j < cbdata.nkeymap; j++)
+ if (cbdata.keymap[j] != i)
+ cbdata.keymap[j] = 0;
+ for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
{
- ll = REPOPAGE_BLOBSIZE - lpage;
- if (l < ll)
- ll = l;
- memcpy(vpage + lpage, dp, ll);
- dp += ll;
- lpage += ll;
- l -= ll;
- if (lpage == REPOPAGE_BLOBSIZE)
+ if (s->repo != repo)
+ continue;
+ FOR_REPODATAS(repo, j, data)
{
- write_compressed_page(fp, vpage, lpage);
- lpage = 0;
+ if (!repodataused[j])
+ continue;
+ if (i < data->start || i >= data->end)
+ continue;
+ repodata_search(data, i, 0, SEARCH_SUB|SEARCH_ARRAYSENTINEL, repo_write_cb_adddata, &cbdata);
+ }
+ if (xd->len > 1024 * 1024)
+ {
+ lpage = write_compressed_extdata(&target, xd, vpage, lpage);
+ xd->len = 0;
}
}
+ if (xd->len)
+ lpage = write_compressed_extdata(&target, xd, vpage, lpage);
}
if (lpage)
- write_compressed_page(fp, vpage, lpage);
+ write_compressed_page(&target, vpage, lpage);
}
for (i = 1; i < target.nkeys; i++)
solv_free(cbdata.extdata[i].buf);
solv_free(cbdata.extdata);
+ target.fp = 0;
repodata_freedata(&target);
solv_free(needid);
solv_free(cbdata.keymapstart);
solv_free(cbdata.dirused);
solv_free(repodataused);
- return 0;
+ return target.error;
}
struct repodata_write_data {