1
0
mirror of https://github.com/openSUSE/libsolv.git synced 2026-02-05 21:45:53 +01:00
Files
libsolv/tools/common_write.c
2018-07-16 15:56:04 +02:00

343 lines
8.7 KiB
C

/*
* Copyright (c) 2007, Novell Inc.
*
* This program is licensed under the BSD license, read LICENSE.BSD
* for further information
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pool.h"
#include "repo.h"
#include "repo_write.h"
#include "common_write.h"
#include "solvversion.h"
/* toolversion history
* 1.0: initial tool version
* 1.1: changed PRODUCT_ENDOFLIFE parsing
*/
static Id verticals[] = {
SOLVABLE_AUTHORS,
SOLVABLE_DESCRIPTION,
SOLVABLE_MESSAGEDEL,
SOLVABLE_MESSAGEINS,
SOLVABLE_EULA,
SOLVABLE_DISKUSAGE,
SOLVABLE_FILELIST,
SOLVABLE_CHANGELOG_AUTHOR,
SOLVABLE_CHANGELOG_TEXT,
0
};
static char *languagetags[] = {
"solvable:summary:",
"solvable:description:",
"solvable:messageins:",
"solvable:messagedel:",
"solvable:eula:",
0
};
static int test_separate = 0;
struct keyfilter_data {
char **languages;
int nlanguages;
int haveaddedfileprovides;
int haveexternal;
};
static int
keyfilter_solv(Repo *data, Repokey *key, void *kfdata)
{
struct keyfilter_data *kd = kfdata;
int i;
const char *keyname;
if (test_separate && key->storage != KEY_STORAGE_SOLVABLE)
return KEY_STORAGE_DROPPED;
if (!kd->haveaddedfileprovides && key->name == REPOSITORY_ADDEDFILEPROVIDES)
return KEY_STORAGE_DROPPED;
if (!kd->haveexternal && key->name == REPOSITORY_EXTERNAL)
return KEY_STORAGE_DROPPED;
if (key->name == SUSETAGS_SHARE_NAME || key->name == SUSETAGS_SHARE_EVR || key->name == SUSETAGS_SHARE_ARCH)
return KEY_STORAGE_DROPPED;
for (i = 0; verticals[i]; i++)
if (key->name == verticals[i])
return KEY_STORAGE_VERTICAL_OFFSET;
keyname = pool_id2str(data->pool, key->name);
for (i = 0; languagetags[i] != 0; i++)
if (!strncmp(keyname, languagetags[i], strlen(languagetags[i])))
return KEY_STORAGE_VERTICAL_OFFSET;
return KEY_STORAGE_INCORE;
}
static int
keyfilter_attr(Repo *data, Repokey *key, void *kfdata)
{
int i;
const char *keyname;
if (key->storage == KEY_STORAGE_SOLVABLE)
return KEY_STORAGE_DROPPED;
/* those must only be in the main solv file */
if (key->name == REPOSITORY_EXTERNAL || key->name == REPOSITORY_ADDEDFILEPROVIDES || key->name == REPOSITORY_TOOLVERSION)
return KEY_STORAGE_DROPPED;
for (i = 0; verticals[i]; i++)
if (key->name == verticals[i])
return KEY_STORAGE_VERTICAL_OFFSET;
keyname = pool_id2str(data->pool, key->name);
for (i = 0; languagetags[i] != 0; i++)
if (!strncmp(keyname, languagetags[i], strlen(languagetags[i])))
return KEY_STORAGE_VERTICAL_OFFSET;
return KEY_STORAGE_INCORE;
}
static int
keyfilter_language(Repo *repo, Repokey *key, void *kfdata)
{
Pool *pool = repo->pool;
const char *name, *p;
char *lang = kfdata;
int i;
name = pool_id2str(repo->pool, key->name);
p = strrchr(name, ':');
if (!p || strcmp(p + 1, lang) != 0)
return KEY_STORAGE_DROPPED;
for (i = 0; verticals[i]; i++)
{
const char *vname = pool_id2str(pool, verticals[i]);
if (!strncmp(name, vname, p - name) && vname[p - name] == 0)
return KEY_STORAGE_VERTICAL_OFFSET;
}
return KEY_STORAGE_INCORE;
}
static int
keyfilter_DU(Repo *repo, Repokey *key, void *kfdata)
{
int i;
if (key->name != SOLVABLE_DISKUSAGE)
return KEY_STORAGE_DROPPED;
for (i = 0; verticals[i]; i++)
if (key->name == verticals[i])
return KEY_STORAGE_VERTICAL_OFFSET;
return KEY_STORAGE_INCORE;
}
static int
keyfilter_FL(Repo *repo, Repokey *key, void *kfdata)
{
int i;
if (key->name != SOLVABLE_FILELIST)
return KEY_STORAGE_DROPPED;
for (i = 0; verticals[i]; i++)
if (key->name == verticals[i])
return KEY_STORAGE_VERTICAL_OFFSET;
return KEY_STORAGE_INCORE;
}
static int
keyfilter_other(Repo *repo, Repokey *key, void *kfdata)
{
const char *name, *p;
struct keyfilter_data *kd = kfdata;
int i;
if (!kd->haveaddedfileprovides && key->name == REPOSITORY_ADDEDFILEPROVIDES)
return KEY_STORAGE_DROPPED;
if (!kd->haveexternal && key->name == REPOSITORY_EXTERNAL)
return KEY_STORAGE_DROPPED;
if (key->name == SOLVABLE_FILELIST || key->name == SOLVABLE_DISKUSAGE)
return KEY_STORAGE_DROPPED;
name = pool_id2str(repo->pool, key->name);
p = strrchr(name, ':');
if (p)
{
for (i = 0; i < kd->nlanguages; i++)
if (!strcmp(p + 1, kd->languages[i]))
return KEY_STORAGE_DROPPED;
}
for (i = 0; verticals[i]; i++)
if (key->name == verticals[i])
return KEY_STORAGE_VERTICAL_OFFSET;
return KEY_STORAGE_INCORE;
}
/*
* Write <repo> to stdout
* If <attrname> is given, write attributes to <attrname>
* If <basename> is given, split attributes
*/
#define REPODATAFILE_BLOCK 15
static void
write_info(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void *kfdata), void *kfdata, Repodata *info, const char *location)
{
Id h;
Queue keyq;
queue_init(&keyq);
if (repo_write_filtered(repo, fp, keyfilter, kfdata, &keyq) != 0)
{
fprintf(stderr, "repo_write failed\n");
exit(1);
}
h = repodata_new_handle(info);
if (keyq.count)
repodata_set_idarray(info, h, REPOSITORY_KEYS, &keyq);
queue_free(&keyq);
repodata_set_str(info, h, REPOSITORY_LOCATION, location);
repodata_add_flexarray(info, SOLVID_META, REPOSITORY_EXTERNAL, h);
}
void
tool_write(Repo *repo, const char *basename, const char *attrname)
{
Repodata *data;
Repodata *info = 0;
Repokey *key;
char **languages = 0;
int nlanguages = 0;
int i, j, k, l;
struct keyfilter_data kd;
Queue addedfileprovides;
memset(&kd, 0, sizeof(kd));
info = repo_add_repodata(repo, 0);
repodata_set_str(info, SOLVID_META, REPOSITORY_TOOLVERSION, LIBSOLV_TOOLVERSION);
queue_init(&addedfileprovides);
pool_addfileprovides_queue(repo->pool, &addedfileprovides, 0);
if (addedfileprovides.count)
{
kd.haveaddedfileprovides = 1;
repodata_set_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &addedfileprovides);
}
queue_free(&addedfileprovides);
pool_freeidhashes(repo->pool); /* free some mem */
if (basename)
{
char fn[4096];
FILE *fp;
int has_DU = 0;
int has_FL = 0;
/* find languages and other info */
FOR_REPODATAS(repo, i, data)
{
for (j = 1, key = data->keys + j; j < data->nkeys; j++, key++)
{
const char *keyname = pool_id2str(repo->pool, key->name);
if (key->name == SOLVABLE_DISKUSAGE)
has_DU = 1;
if (key->name == SOLVABLE_FILELIST)
has_FL = 1;
for (k = 0; languagetags[k] != 0; k++)
if (!strncmp(keyname, languagetags[k], strlen(languagetags[k])))
break;
if (!languagetags[k])
continue;
l = strlen(languagetags[k]);
if (strlen(keyname + l) > 5)
continue;
for (k = 0; k < nlanguages; k++)
if (!strcmp(languages[k], keyname + l))
break;
if (k < nlanguages)
continue;
languages = solv_realloc2(languages, nlanguages + 1, sizeof(char *));
languages[nlanguages++] = strdup(keyname + l);
}
}
/* write language subfiles */
for (i = 0; i < nlanguages; i++)
{
sprintf(fn, "%s.%s.solv", basename, languages[i]);
if (!(fp = fopen(fn, "w")))
{
perror(fn);
exit(1);
}
write_info(repo, fp, keyfilter_language, languages[i], info, fn);
fclose(fp);
kd.haveexternal = 1;
}
/* write DU subfile */
if (has_DU)
{
sprintf(fn, "%s.DU.solv", basename);
if (!(fp = fopen(fn, "w")))
{
perror(fn);
exit(1);
}
write_info(repo, fp, keyfilter_DU, 0, info, fn);
fclose(fp);
kd.haveexternal = 1;
}
/* write filelist */
if (has_FL)
{
sprintf(fn, "%s.FL.solv", basename);
if (!(fp = fopen(fn, "w")))
{
perror(fn);
exit(1);
}
write_info(repo, fp, keyfilter_FL, 0, info, fn);
fclose(fp);
kd.haveexternal = 1;
}
/* write everything else */
sprintf(fn, "%s.solv", basename);
if (!(fp = fopen(fn, "w")))
{
perror(fn);
exit(1);
}
kd.languages = languages;
kd.nlanguages = nlanguages;
repodata_internalize(info);
if (repo_write_filtered(repo, fp, keyfilter_other, &kd, 0) != 0)
{
fprintf(stderr, "repo_write failed\n");
exit(1);
}
if (fclose(fp) != 0)
{
perror("fclose");
exit(1);
}
for (i = 0; i < nlanguages; i++)
free(languages[i]);
solv_free(languages);
repodata_free(info);
}
if (attrname)
{
FILE *fp;
test_separate = 1;
fp = fopen(attrname, "w");
write_info(repo, fp, keyfilter_attr, 0, info, attrname);
fclose(fp);
kd.haveexternal = 1;
}
repodata_internalize(info);
if (repo_write_filtered(repo, stdout, keyfilter_solv, &kd, 0) != 0)
{
fprintf(stderr, "repo_write failed\n");
exit(1);
}
repodata_free(info);
}