aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gregory <andrew.gregory.8@gmail.com>2022-02-06 10:08:46 -0800
committerAllan McRae <allan@archlinux.org>2022-07-21 19:01:27 +1000
commit3405709b463db4c566ccd7c9c9ad42594a9c6076 (patch)
tree42ab396aba07ea724e6644b7fb33d712063eb91c
parent2bf67416c17c99851e2d0bbc5c4b269a6bd8de8b (diff)
add extended data field for arbitrary package data
This adds a mechanism for package builders to add arbitrary data to packages that is not necessarily relevant enough to the package installation process to gain first-class support in alpm. Currently these fields have to be added to parsers with a "not actually used" comment and can't be retrieved through the API. Extended data is stored in "name=value" format in the xdata field (%XDATA% in desc files): xdata = pkgtype=debug or %XDATA% pkgtype=debug Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
-rw-r--r--lib/libalpm/alpm.h7
-rw-r--r--lib/libalpm/be_local.c28
-rw-r--r--lib/libalpm/be_package.c6
-rw-r--r--lib/libalpm/be_sync.c12
-rw-r--r--lib/libalpm/package.c35
-rw-r--r--lib/libalpm/package.h7
6 files changed, 95 insertions, 0 deletions
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index cdf71fdc..3304ae77 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -2291,6 +2291,13 @@ typedef enum _alpm_pkgvalidation_t {
ALPM_PKG_VALIDATION_SIGNATURE = (1 << 3)
} alpm_pkgvalidation_t;
+typedef struct _alpm_pkg_xdata_t {
+ char *name;
+ char *value;
+} alpm_pkg_xdata_t;
+
+alpm_list_t *alpm_pkg_get_xdata(alpm_pkg_t *pkg);
+
/** Create a package from a file.
* If full is false, the archive is read only until all necessary
* metadata is found. If it is true, the entire archive is read, which
diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c
index 87fecbe5..e117b69d 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -195,6 +195,12 @@ static alpm_list_t *_cache_get_backup(alpm_pkg_t *pkg)
return pkg->backup;
}
+static alpm_list_t *_cache_get_xdata(alpm_pkg_t *pkg)
+{
+ LAZY_LOAD(INFRQ_DESC);
+ return pkg->xdata;
+}
+
/**
* Open a package changelog for reading. Similar to fopen in functionality,
* except that the returned 'file stream' is from the database.
@@ -349,6 +355,7 @@ static const struct pkg_operations local_pkg_ops = {
.get_replaces = _cache_get_replaces,
.get_files = _cache_get_files,
.get_backup = _cache_get_backup,
+ .get_xdata = _cache_get_xdata,
.changelog_open = _cache_changelog_open,
.changelog_read = _cache_changelog_read,
@@ -804,6 +811,18 @@ static int local_db_read(alpm_pkg_t *info, int inforeq)
READ_AND_SPLITDEP(info->conflicts);
} else if(strcmp(line, "%PROVIDES%") == 0) {
READ_AND_SPLITDEP(info->provides);
+ } else if(strcmp(line, "%XDATA%") == 0) {
+ alpm_list_t *i, *lines = NULL;
+ READ_AND_STORE_ALL(lines);
+ for(i = lines; i; i = i->next) {
+ alpm_pkg_xdata_t *pd = _alpm_pkg_parse_xdata(i->data);
+ if(pd == NULL || !alpm_list_append(&info->xdata, pd)) {
+ _alpm_pkg_xdata_free(pd);
+ FREELIST(lines);
+ goto error;
+ }
+ }
+ FREELIST(lines);
}
}
fclose(fp);
@@ -1040,6 +1059,15 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, int inforeq)
write_deps(fp, "%CONFLICTS%", info->conflicts);
write_deps(fp, "%PROVIDES%", info->provides);
+ if(info->xdata) {
+ fputs("%XDATA%\n", fp);
+ for(lp = info->xdata; lp; lp = lp->next) {
+ alpm_pkg_xdata_t *pd = lp->data;
+ fprintf(fp, "%s=%s\n", pd->name, pd->value);
+ }
+ fputc('\n', fp);
+ }
+
fclose(fp);
fp = NULL;
}
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index 203c98c1..b4f3f1c2 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -246,6 +246,12 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *
newpkg->backup = alpm_list_add(newpkg->backup, backup);
} else if(strcmp(key, "pkgtype") == 0) {
/* not used atm */
+ } else if(strcmp(key, "xdata") == 0) {
+ alpm_pkg_xdata_t *pd = _alpm_pkg_parse_xdata(ptr);
+ if(pd == NULL || !alpm_list_append(&newpkg->xdata, pd)) {
+ _alpm_pkg_xdata_free(pd);
+ return -1;
+ }
} else {
_alpm_log(handle, ALPM_LOG_DEBUG, "%s: unknown key '%s' in description file line %d\n",
newpkg->name ? newpkg->name : "error", key, linenum);
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index 8c8e01a0..81676be9 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -666,6 +666,18 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
pkg->files.count = files_count;
pkg->files.files = files;
_alpm_filelist_sort(&pkg->files);
+ } else if(strcmp(line, "%DATA%") == 0) {
+ alpm_list_t *i, *lines = NULL;
+ READ_AND_STORE_ALL(lines);
+ for(i = lines; i; i = i->next) {
+ alpm_pkg_xdata_t *pd = _alpm_pkg_parse_xdata(i->data);
+ if(pd == NULL || !alpm_list_append(&pkg->xdata, pd)) {
+ _alpm_pkg_xdata_free(pd);
+ FREELIST(lines);
+ goto error;
+ }
+ }
+ FREELIST(lines);
}
}
if(ret != ARCHIVE_EOF) {
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index 4d89dcd8..8c95dab3 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -98,6 +98,7 @@ static alpm_list_t *_pkg_get_provides(alpm_pkg_t *pkg) { return pkg->provides;
static alpm_list_t *_pkg_get_replaces(alpm_pkg_t *pkg) { return pkg->replaces; }
static alpm_filelist_t *_pkg_get_files(alpm_pkg_t *pkg) { return &(pkg->files); }
static alpm_list_t *_pkg_get_backup(alpm_pkg_t *pkg) { return pkg->backup; }
+static alpm_list_t *_pkg_get_xdata(alpm_pkg_t *pkg) { return pkg->xdata; }
static void *_pkg_changelog_open(alpm_pkg_t UNUSED *pkg)
{
@@ -162,6 +163,7 @@ const struct pkg_operations default_pkg_ops = {
.get_replaces = _pkg_get_replaces,
.get_files = _pkg_get_files,
.get_backup = _pkg_get_backup,
+ .get_xdata = _pkg_get_xdata,
.changelog_open = _pkg_changelog_open,
.changelog_read = _pkg_changelog_read,
@@ -485,6 +487,13 @@ int SYMEXPORT alpm_pkg_has_scriptlet(alpm_pkg_t *pkg)
return pkg->ops->has_scriptlet(pkg);
}
+alpm_list_t SYMEXPORT *alpm_pkg_get_xdata(alpm_pkg_t *pkg)
+{
+ ASSERT(pkg != NULL, return NULL);
+ pkg->handle->pm_errno = ALPM_ERR_OK;
+ return pkg->ops->get_xdata(pkg);
+}
+
static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, alpm_list_t **reqs,
int optional)
{
@@ -677,6 +686,30 @@ static void free_deplist(alpm_list_t *deps)
alpm_list_free(deps);
}
+alpm_pkg_xdata_t *_alpm_pkg_parse_xdata(const char *string)
+{
+ alpm_pkg_xdata_t *pd;
+ const char *sep;
+ if(string == NULL || (sep = strchr(string, '=')) == NULL) {
+ return NULL;
+ }
+
+ CALLOC(pd, 1, sizeof(alpm_pkg_xdata_t), return NULL);
+ STRNDUP(pd->name, string, sep - string, FREE(pd); return NULL);
+ STRDUP(pd->value, sep + 1, FREE(pd->name); FREE(pd); return NULL);
+
+ return pd;
+}
+
+void _alpm_pkg_xdata_free(alpm_pkg_xdata_t *pd)
+{
+ if(pd) {
+ free(pd->name);
+ free(pd->value);
+ free(pd);
+ }
+}
+
void _alpm_pkg_free(alpm_pkg_t *pkg)
{
if(pkg == NULL) {
@@ -707,6 +740,8 @@ void _alpm_pkg_free(alpm_pkg_t *pkg)
}
alpm_list_free_inner(pkg->backup, (alpm_list_fn_free)_alpm_backup_free);
alpm_list_free(pkg->backup);
+ alpm_list_free_inner(pkg->xdata, (alpm_list_fn_free)_alpm_pkg_xdata_free);
+ alpm_list_free(pkg->xdata);
free_deplist(pkg->depends);
free_deplist(pkg->optdepends);
free_deplist(pkg->checkdepends);
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index 93522530..5ebe6bd1 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -67,6 +67,8 @@ struct pkg_operations {
alpm_filelist_t *(*get_files) (alpm_pkg_t *);
alpm_list_t *(*get_backup) (alpm_pkg_t *);
+ alpm_list_t *(*get_xdata) (alpm_pkg_t *);
+
void *(*changelog_open) (alpm_pkg_t *);
size_t (*changelog_read) (void *, size_t, const alpm_pkg_t *, void *);
int (*changelog_close) (const alpm_pkg_t *, void *);
@@ -136,6 +138,8 @@ struct _alpm_pkg_t {
alpm_pkgreason_t reason;
int scriptlet;
+ alpm_list_t *xdata;
+
/* Bitfield from alpm_dbinfrq_t */
int infolevel;
/* Bitfield from alpm_pkgvalidation_t */
@@ -158,4 +162,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
int _alpm_pkg_cmp(const void *p1, const void *p2);
int _alpm_pkg_compare_versions(alpm_pkg_t *local_pkg, alpm_pkg_t *pkg);
+alpm_pkg_xdata_t *_alpm_pkg_parse_xdata(const char *string);
+void _alpm_pkg_xdata_free(alpm_pkg_xdata_t *pd);
+
#endif /* ALPM_PACKAGE_H */