This adds a mechanism for package builders to add arbitrary data to
packages that is not necessarily relevant 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.

In ini format these are represented by prefixing the field name with
"data-" similar to HTML5 data attributes.  In db format they are put
into a "%DATA%" section in the format "<key> <value>".

Signed-off-by: Andrew Gregory <[email protected]>
---
 lib/libalpm/alpm.h       |  7 +++++++
 lib/libalpm/be_local.c   | 25 +++++++++++++++++++++++++
 lib/libalpm/be_package.c |  6 ++++++
 lib/libalpm/be_sync.c    | 16 ++++++++++++++++
 lib/libalpm/package.c    | 17 +++++++++++++++++
 lib/libalpm/package.h    |  6 ++++++
 6 files changed, 77 insertions(+)

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 50b5e3d2..b1c6262e 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -2285,6 +2285,13 @@ typedef enum _alpm_pkgvalidation_t {
        ALPM_PKG_VALIDATION_SIGNATURE = (1 << 3)
 } alpm_pkgvalidation_t;
 
+typedef struct _alpm_pkg_data_t {
+       char *name;
+       char *value;
+} alpm_pkg_data_t;
+
+alpm_list_t *alpm_pkg_get_data(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..74745a98 100644
--- a/lib/libalpm/be_local.c
+++ b/lib/libalpm/be_local.c
@@ -804,6 +804,22 @@ 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, "%DATA%") == 0) {
+                               while(1) {
+                                       alpm_pkg_data_t *pd;
+                                       char *sep;
+                                       READ_NEXT();
+                                       if(line[0] == '\0') {
+                                               break;
+                                       }
+                                       if((sep = strchr(line, ' ')) == NULL) {
+                                               goto error;
+                                       }
+                                       CALLOC(pd, 1, sizeof(alpm_pkg_data_t), 
goto error);
+                                       STRNDUP(pd->name, line, sep - line, 
_alpm_pkg_data_free(pd); goto error);
+                                       STRDUP(pd->value, sep, 
_alpm_pkg_data_free(pd); goto error);
+                                       info->xdata = 
alpm_list_add(info->xdata, pd);
+                               }
                        }
                }
                fclose(fp);
@@ -1040,6 +1056,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("%DATA%\n", fp);
+                       for(lp = info->xdata; lp; lp = lp->next) {
+                               alpm_pkg_data_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 e837ffb8..1fef308d 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(strncmp(key, "data-", 5) == 0 && key[5] != 
'\0') {
+                               alpm_pkg_data_t *pd;
+                               CALLOC(pd, 1, sizeof(alpm_pkg_data_t), return 
-1);
+                               STRDUP(pd->name, key + 5, 
_alpm_pkg_data_free(pd); return -1);
+                               STRDUP(pd->value, ptr, _alpm_pkg_data_free(pd); 
return -1);
+                               newpkg->xdata = alpm_list_add(newpkg->xdata, 
pd);
                        } 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..9566294a 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -666,6 +666,22 @@ 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) {
+                               while(1) {
+                                       alpm_pkg_data_t *pd;
+                                       char *sep;
+                                       READ_NEXT();
+                                       if(line[0] == '\0') {
+                                               break;
+                                       }
+                                       if((sep = strchr(line, ' ')) == NULL) {
+                                               goto error;
+                                       }
+                                       CALLOC(pd, 1, sizeof(alpm_pkg_data_t), 
goto error);
+                                       STRNDUP(pd->name, line, sep - line, 
FREE(pd); goto error);
+                                       STRDUP(pd->value, sep, FREE(pd->name); 
FREE(pd); goto error);
+                                       pkg->xdata = alpm_list_add(pkg->xdata, 
pd);
+                               }
                        }
                }
                if(ret != ARCHIVE_EOF) {
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index e79d7d65..c7b7f745 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_data(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_data        = _pkg_get_data,
 
        .changelog_open  = _pkg_changelog_open,
        .changelog_read  = _pkg_changelog_read,
@@ -479,6 +481,13 @@ int SYMEXPORT alpm_pkg_has_scriptlet(alpm_pkg_t *pkg)
        return pkg->ops->has_scriptlet(pkg);
 }
 
+alpm_list_t SYMEXPORT *alpm_pkg_get_data(alpm_pkg_t *pkg)
+{
+       ASSERT(pkg != NULL, return NULL);
+       pkg->handle->pm_errno = ALPM_ERR_OK;
+       return pkg->ops->get_data(pkg);
+}
+
 static void find_requiredby(alpm_pkg_t *pkg, alpm_db_t *db, alpm_list_t **reqs,
                int optional)
 {
@@ -671,6 +680,14 @@ static void free_deplist(alpm_list_t *deps)
        alpm_list_free(deps);
 }
 
+void _alpm_pkg_data_free(alpm_pkg_data_t *pd) {
+       if(pd) {
+               free(pd->name);
+               free(pd->value);
+               free(pd);
+       }
+}
+
 void _alpm_pkg_free(alpm_pkg_t *pkg)
 {
        if(pkg == NULL) {
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index 93522530..05775077 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_data) (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,6 @@ 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);
 
+void _alpm_pkg_data_free(alpm_pkg_data_t *pd);
+
 #endif /* ALPM_PACKAGE_H */
-- 
2.35.0

Reply via email to