pkg: use a blob buffer in pkg_t to store variable fields
authorJo-Philipp Wich <jo@mein.io>
Fri, 10 Feb 2017 16:14:53 +0000 (17:14 +0100)
committerJo-Philipp Wich <jo@mein.io>
Mon, 13 Feb 2017 15:52:56 +0000 (16:52 +0100)
Adds infrastructure to use a blob buffer in pkg_t to store and retrieve
optional dynamic fields.

This reduces the size of the pkg_t structure itself and lays the
ground work for further optimization.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
14 files changed:
libopkg/opkg.c
libopkg/opkg_cmd.c
libopkg/opkg_download.c
libopkg/opkg_install.c
libopkg/pkg.c
libopkg/pkg.h
libopkg/pkg_depends.c
libopkg/pkg_extract.c
libopkg/pkg_hash.c
libopkg/pkg_parse.c
libopkg/pkg_vec.c
src/Makefile.am
tests/Makefile.am
tests/libopkg_test.c

index 351983d..61c7306 100644 (file)
@@ -239,12 +239,13 @@ opkg_install_package(const char *package_name,
                     void *user_data)
 {
        int err;
-       char *stripped_filename;
+       char *stripped_filename, *local_filename;
        opkg_progress_data_t pdata;
        pkg_t *old, *new;
        pkg_vec_t *deps, *all;
        int i, ndepends;
        char **unresolved = NULL;
+       const char *filename;
 
        opkg_assert(package_name != NULL);
 
@@ -302,7 +303,7 @@ opkg_install_package(const char *package_name,
                char *url;
 
                pkg = deps->pkgs[i];
-               if (pkg->local_filename)
+               if (pkg_get_string(pkg, PKG_LOCAL_FILENAME))
                        continue;
 
                pdata.pkg = pkg;
@@ -314,16 +315,20 @@ opkg_install_package(const char *package_name,
                        return -1;
                }
 
-               sprintf_alloc(&url, "%s/%s", pkg->src->value, pkg->filename);
+               filename = pkg_get_string(pkg, PKG_FILENAME);
+
+               sprintf_alloc(&url, "%s/%s", pkg->src->value, filename);
 
                /* Get the filename part, without any directory */
-               stripped_filename = strrchr(pkg->filename, '/');
+               stripped_filename = strrchr(filename, '/');
                if (!stripped_filename)
-                       stripped_filename = pkg->filename;
+                       stripped_filename = (char *)filename;
 
-               sprintf_alloc(&pkg->local_filename, "%s/%s", conf->tmp_dir,
+               sprintf_alloc(&local_filename, "%s/%s", conf->tmp_dir,
                              stripped_filename);
 
+               pkg_set_string(pkg, PKG_LOCAL_FILENAME, local_filename);
+
                cb_data.cb = progress_callback;
                cb_data.progress_data = &pdata;
                cb_data.user_data = user_data;
@@ -331,7 +336,7 @@ opkg_install_package(const char *package_name,
                cb_data.start_range = 75 * i / deps->len;
                cb_data.finish_range = 75 * (i + 1) / deps->len;
 
-               err = opkg_download(url, pkg->local_filename,
+               err = opkg_download(url, local_filename,
                                    (curl_progress_func) curl_progress_cb,
                                    &cb_data, 0);
                free(url);
@@ -744,7 +749,7 @@ pkg_t *opkg_find_package(const char *name, const char *ver, const char *arch,
 
                /* check architecture */
                if (arch) {
-                       if (sstrcmp(pkg->architecture, arch))
+                       if (sstrcmp(pkg_get_string(pkg, PKG_ARCHITECTURE), arch))
                                continue;
                }
 
index d03e27c..2e286ab 100644 (file)
 static void print_pkg(pkg_t * pkg)
 {
        char *version = pkg_version_str_alloc(pkg);
+       char *description = pkg_get_string(pkg, PKG_DESCRIPTION);
        printf("%s - %s", pkg->name, version);
        if (conf->size)
                printf(" - %lu", pkg->size);
-       if (pkg->description)
-               printf(" - %s", pkg->description);
+       if (description)
+               printf(" - %s", description);
        printf("\n");
        free(version);
 }
@@ -553,7 +554,7 @@ static int opkg_download_cmd(int argc, char **argv)
                        opkg_msg(ERROR, "Failed to download %s.\n", pkg->name);
                } else {
                        opkg_msg(NOTICE, "Downloaded %s as %s.\n",
-                                pkg->name, pkg->local_filename);
+                                pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME));
                }
        }
 
@@ -566,6 +567,7 @@ static int opkg_list_find_cmd(int argc, char **argv, int use_desc)
        pkg_vec_t *available;
        pkg_t *pkg;
        char *pkg_name = NULL;
+       char *description;
 
        if (argc > 0) {
                pkg_name = argv[0];
@@ -575,10 +577,11 @@ static int opkg_list_find_cmd(int argc, char **argv, int use_desc)
        pkg_vec_sort(available, pkg_compare_names);
        for (i = 0; i < available->len; i++) {
                pkg = available->pkgs[i];
+               description = use_desc ? pkg_get_string(pkg, PKG_DESCRIPTION) : NULL;
                /* if we have package name or pattern and pkg does not match, then skip it */
                if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase) &&
-                   (!use_desc || !pkg->description
-                    || fnmatch(pkg_name, pkg->description, conf->nocase)))
+                   (!use_desc || !description
+                    || fnmatch(pkg_name, description, conf->nocase)))
                        continue;
                print_pkg(pkg);
        }
index 260790b..55e71a6 100644 (file)
@@ -253,7 +253,9 @@ int opkg_download_pkg(pkg_t * pkg, const char *dir)
 {
        int err;
        char *url;
+       char *local_filename;
        char *stripped_filename;
+       char *filename;
 
        if (pkg->src == NULL) {
                opkg_msg(ERROR,
@@ -261,27 +263,31 @@ int opkg_download_pkg(pkg_t * pkg, const char *dir)
                         pkg->name);
                return -1;
        }
-       if (pkg->filename == NULL) {
+
+       filename = pkg_get_string(pkg, PKG_FILENAME);
+
+       if (filename == NULL) {
                opkg_msg(ERROR,
                         "Package %s does not have a valid filename field.\n",
                         pkg->name);
                return -1;
        }
 
-       sprintf_alloc(&url, "%s/%s", pkg->src->value, pkg->filename);
+       sprintf_alloc(&url, "%s/%s", pkg->src->value, filename);
 
-       /* The pkg->filename might be something like
+       /* The filename might be something like
           "../../foo.opk". While this is correct, and exactly what we
           want to use to construct url above, here we actually need to
           use just the filename part, without any directory. */
 
-       stripped_filename = strrchr(pkg->filename, '/');
+       stripped_filename = strrchr(filename, '/');
        if (!stripped_filename)
-               stripped_filename = pkg->filename;
+               stripped_filename = filename;
 
-       sprintf_alloc(&pkg->local_filename, "%s/%s", dir, stripped_filename);
+       sprintf_alloc(&local_filename, "%s/%s", dir, stripped_filename);
+       pkg_set_string(pkg, PKG_LOCAL_FILENAME, local_filename);
 
-       err = opkg_download_cache(url, pkg->local_filename, NULL, NULL);
+       err = opkg_download_cache(url, local_filename, NULL, NULL);
        free(url);
 
        return err;
@@ -323,7 +329,7 @@ int opkg_prepare_url_for_install(const char *url, char **namep)
                if (err)
                        return err;
                opkg_msg(DEBUG2, "Package %s provided by hand (%s).\n",
-                        pkg->name, pkg->local_filename);
+                        pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME));
                pkg->provided_by_hand = 1;
 
        } else {
index 76b658d..08b40fb 100644 (file)
@@ -1182,7 +1182,7 @@ int opkg_install_by_name(const char *pkg_name)
        old = pkg_hash_fetch_installed_by_name(pkg_name);
        if (old)
                opkg_msg(DEBUG2, "Old versions from pkg_hash_fetch %s.\n",
-                        old->version);
+                        pkg_get_string(old, PKG_VERSION));
 
        new = pkg_hash_fetch_best_installation_candidate_by_name(pkg_name);
        if (new == NULL) {
@@ -1192,8 +1192,8 @@ int opkg_install_by_name(const char *pkg_name)
 
        opkg_msg(DEBUG2, "Versions from pkg_hash_fetch:");
        if (old)
-               opkg_message(DEBUG2, " old %s ", old->version);
-       opkg_message(DEBUG2, " new %s\n", new->version);
+               opkg_message(DEBUG2, " old %s ", pkg_get_string(old, PKG_VERSION));
+       opkg_message(DEBUG2, " new %s\n", pkg_get_string(new, PKG_VERSION));
 
        new->state_flag |= SF_USER;
        if (old) {
@@ -1250,11 +1250,12 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
        pkg_vec_t *replacees;
        abstract_pkg_t *ab_pkg = NULL;
        int old_state_flag;
-       char *file_md5;
+       char *file_md5, *pkg_md5;
 #ifdef HAVE_SHA256
-       char *file_sha256;
+       char *file_sha256, *pkg_sha256;
 #endif
        sigset_t newset, oldset;
+       const char *local_filename;
 
        if (from_upgrade)
                message = 1;    /* Coming from an upgrade, and should change the output message */
@@ -1264,7 +1265,7 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
        if (!pkg_arch_supported(pkg)) {
                opkg_msg(ERROR,
                         "INTERNAL ERROR: architecture %s for pkg %s is unsupported.\n",
-                        pkg->architecture, pkg->name);
+                        pkg_get_string(pkg, PKG_ARCHITECTURE), pkg->name);
                return -1;
        }
        if (pkg->state_status == SS_INSTALLED && conf->nodeps == 0) {
@@ -1307,7 +1308,9 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
        if (err)
                return -1;
 
-       if (pkg->local_filename == NULL) {
+       local_filename = pkg_get_string(pkg, PKG_LOCAL_FILENAME);
+
+       if (local_filename == NULL) {
                if (!conf->cache && conf->download_only) {
                        char cwd[4096];
                        if (getcwd(cwd, sizeof(cwd)) != NULL)
@@ -1363,9 +1366,10 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
 
 #ifdef HAVE_MD5
        /* Check for md5 values */
-       if (pkg->md5sum) {
-               file_md5 = file_md5sum_alloc(pkg->local_filename);
-               if (file_md5 && strcmp(file_md5, pkg->md5sum)) {
+       pkg_md5 = pkg_get_string(pkg, PKG_MD5SUM);
+       if (pkg_md5) {
+               file_md5 = file_md5sum_alloc(local_filename);
+               if (file_md5 && strcmp(file_md5, pkg_md5)) {
                        if (!conf->force_checksum) {
                                opkg_msg(ERROR, "Package %s md5sum mismatch. "
                                         "Either the opkg or the package index are corrupt. "
@@ -1385,9 +1389,10 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
 
 #ifdef HAVE_SHA256
        /* Check for sha256 value */
-       if (pkg->sha256sum) {
-               file_sha256 = file_sha256sum_alloc(pkg->local_filename);
-               if (file_sha256 && strcmp(file_sha256, pkg->sha256sum)) {
+       pkg_sha256 = pkg_get_string(pkg, PKG_SHA256SUM);
+       if (pkg_sha256) {
+               file_sha256 = file_sha256sum_alloc(local_filename);
+               if (file_sha256 && strcmp(file_sha256, pkg_sha256)) {
                        if (!conf->force_checksum) {
                                opkg_msg(ERROR,
                                         "Package %s sha256sum mismatch. "
@@ -1418,7 +1423,7 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
                if (unpack_pkg_control_files(pkg) == -1) {
                        opkg_msg(ERROR,
                                 "Failed to unpack control files from %s.\n",
-                                pkg->local_filename);
+                                local_filename);
                        return -1;
                }
        }
index 41aaff8..30602bf 100644 (file)
@@ -74,15 +74,8 @@ static const enum_map_t pkg_state_status_map[] = {
 static void pkg_init(pkg_t * pkg)
 {
        pkg->name = NULL;
-       pkg->epoch = 0;
-       pkg->version = NULL;
-       pkg->revision = NULL;
        pkg->dest = NULL;
        pkg->src = NULL;
-       pkg->architecture = NULL;
-       pkg->maintainer = NULL;
-       pkg->section = NULL;
-       pkg->description = NULL;
        pkg->state_want = SW_UNKNOWN;
        pkg->state_flag = SF_OK;
        pkg->state_status = SS_NOT_INSTALLED;
@@ -107,22 +100,16 @@ static void pkg_init(pkg_t * pkg)
        pkg->pre_depends_str = NULL;
        pkg->provides_count = 0;
        pkg->provides = NULL;
-       pkg->filename = NULL;
-       pkg->local_filename = NULL;
        pkg->tmp_unpack_dir = NULL;
-       pkg->md5sum = NULL;
-#if defined HAVE_SHA256
-       pkg->sha256sum = NULL;
-#endif
        pkg->size = 0;
        pkg->installed_size = 0;
-       pkg->priority = NULL;
-       pkg->source = NULL;
        conffile_list_init(&pkg->conffiles);
        pkg->installed_files = NULL;
        pkg->installed_files_ref_cnt = 0;
        pkg->essential = 0;
        pkg->provided_by_hand = 0;
+
+       blob_buf_init(&pkg->blob, 0);
 }
 
 pkg_t *pkg_new(void)
@@ -135,6 +122,66 @@ pkg_t *pkg_new(void)
        return pkg;
 }
 
+void *pkg_set_raw(pkg_t *pkg, int id, const void *val, size_t len)
+{
+       int rem;
+       struct blob_attr *cur;
+
+       blob_for_each_attr(cur, pkg->blob.head, rem) {
+               if (blob_id(cur) == id) {
+                       if (blob_len(cur) < len) {
+                               fprintf(stderr, "ERROR: truncating field %d <%p> to %d byte",
+                                       id, val, blob_len(cur));
+                       }
+                       memcpy(blob_data(cur), val, blob_len(cur));
+                       return blob_data(cur);
+               }
+       }
+
+       cur = blob_put(&pkg->blob, id, val, len);
+       return cur ? blob_data(cur) : NULL;
+}
+
+void *pkg_get_raw(const pkg_t * pkg, int id)
+{
+       int rem;
+       struct blob_attr *cur;
+
+       blob_for_each_attr(cur, pkg->blob.head, rem)
+               if (blob_id(cur) == id)
+                       return blob_data(cur);
+
+       return NULL;
+}
+
+char *pkg_set_string(pkg_t *pkg, int id, const char *s)
+{
+       size_t len;
+       char *p;
+
+       if (!s)
+               return NULL;
+
+       len = strlen(s);
+
+       while (isspace(*s)) {
+               s++;
+               len--;
+       }
+
+       while (len > 0 && isspace(s[len - 1]))
+               len--;
+
+       if (!len)
+               return NULL;
+
+       p = pkg_set_raw(pkg, id, s, len + 1);
+       p[len] = 0;
+
+       return p;
+}
+
+
 static void compound_depend_deinit(compound_depend_t * depends)
 {
        int i;
@@ -155,35 +202,11 @@ void pkg_deinit(pkg_t * pkg)
                free(pkg->name);
        pkg->name = NULL;
 
-       pkg->epoch = 0;
-
-       if (pkg->version)
-               free(pkg->version);
-       pkg->version = NULL;
-       /* revision shares storage with version, so don't free */
-       pkg->revision = NULL;
-
        /* owned by opkg_conf_t */
        pkg->dest = NULL;
        /* owned by opkg_conf_t */
        pkg->src = NULL;
 
-       if (pkg->architecture)
-               free(pkg->architecture);
-       pkg->architecture = NULL;
-
-       if (pkg->maintainer)
-               free(pkg->maintainer);
-       pkg->maintainer = NULL;
-
-       if (pkg->section)
-               free(pkg->section);
-       pkg->section = NULL;
-
-       if (pkg->description)
-               free(pkg->description);
-       pkg->description = NULL;
-
        pkg->state_want = SW_UNKNOWN;
        pkg->state_flag = SF_OK;
        pkg->state_status = SS_NOT_INSTALLED;
@@ -216,14 +239,6 @@ void pkg_deinit(pkg_t * pkg)
        pkg->pre_depends_count = 0;
        pkg->provides_count = 0;
 
-       if (pkg->filename)
-               free(pkg->filename);
-       pkg->filename = NULL;
-
-       if (pkg->local_filename)
-               free(pkg->local_filename);
-       pkg->local_filename = NULL;
-
        /* CLEANUP: It'd be nice to pullin the cleanup function from
           opkg_install.c here. See comment in
           opkg_install.c:cleanup_temporary_files */
@@ -231,24 +246,6 @@ void pkg_deinit(pkg_t * pkg)
                free(pkg->tmp_unpack_dir);
        pkg->tmp_unpack_dir = NULL;
 
-       if (pkg->md5sum)
-               free(pkg->md5sum);
-       pkg->md5sum = NULL;
-
-#if defined HAVE_SHA256
-       if (pkg->sha256sum)
-               free(pkg->sha256sum);
-       pkg->sha256sum = NULL;
-#endif
-
-       if (pkg->priority)
-               free(pkg->priority);
-       pkg->priority = NULL;
-
-       if (pkg->source)
-               free(pkg->source);
-       pkg->source = NULL;
-
        conffile_list_deinit(&pkg->conffiles);
 
        /* XXX: QUESTION: Is forcing this to 1 correct? I suppose so,
@@ -258,9 +255,7 @@ void pkg_deinit(pkg_t * pkg)
        pkg_free_installed_files(pkg);
        pkg->essential = 0;
 
-       if (pkg->tags)
-               free(pkg->tags);
-       pkg->tags = NULL;
+       blob_buf_free(&pkg->blob);
 }
 
 int pkg_init_from_file(pkg_t * pkg, const char *filename)
@@ -271,7 +266,7 @@ int pkg_init_from_file(pkg_t * pkg, const char *filename)
 
        pkg_init(pkg);
 
-       pkg->local_filename = xstrdup(filename);
+       pkg_set_string(pkg, PKG_LOCAL_FILENAME, filename);
 
        tmp = xstrdup(filename);
        sprintf_alloc(&control_path, "%s/%s.control.XXXXXX",
@@ -333,16 +328,16 @@ int pkg_merge(pkg_t * oldpkg, pkg_t * newpkg)
                oldpkg->src = newpkg->src;
        if (!oldpkg->dest)
                oldpkg->dest = newpkg->dest;
-       if (!oldpkg->architecture)
-               oldpkg->architecture = xstrdup(newpkg->architecture);
+       if (!pkg_get_string(oldpkg, PKG_ARCHITECTURE))
+               pkg_set_string(oldpkg, PKG_ARCHITECTURE, pkg_get_string(newpkg, PKG_ARCHITECTURE));
        if (!oldpkg->arch_priority)
                oldpkg->arch_priority = newpkg->arch_priority;
-       if (!oldpkg->section)
-               oldpkg->section = xstrdup(newpkg->section);
-       if (!oldpkg->maintainer)
-               oldpkg->maintainer = xstrdup(newpkg->maintainer);
-       if (!oldpkg->description)
-               oldpkg->description = xstrdup(newpkg->description);
+       if (!pkg_get_string(oldpkg, PKG_SECTION))
+               pkg_set_string(oldpkg, PKG_SECTION, pkg_get_string(newpkg, PKG_SECTION));
+       if (!pkg_get_string(oldpkg, PKG_MAINTAINER))
+               pkg_set_string(oldpkg, PKG_MAINTAINER, pkg_get_string(newpkg, PKG_MAINTAINER));
+       if (!pkg_get_string(oldpkg, PKG_DESCRIPTION))
+               pkg_set_string(oldpkg, PKG_DESCRIPTION, pkg_get_string(newpkg, PKG_DESCRIPTION));
 
        if (!oldpkg->depends_count && !oldpkg->pre_depends_count
            && !oldpkg->recommends_count && !oldpkg->suggests_count) {
@@ -388,26 +383,24 @@ int pkg_merge(pkg_t * oldpkg, pkg_t * newpkg)
                newpkg->replaces = NULL;
        }
 
-       if (!oldpkg->filename)
-               oldpkg->filename = xstrdup(newpkg->filename);
-       if (!oldpkg->local_filename)
-               oldpkg->local_filename = xstrdup(newpkg->local_filename);
+       if (!pkg_get_string(oldpkg, PKG_FILENAME))
+               pkg_set_string(oldpkg, PKG_FILENAME, pkg_get_string(newpkg, PKG_FILENAME));
+       if (!pkg_get_string(oldpkg, PKG_LOCAL_FILENAME))
+               pkg_set_string(oldpkg, PKG_LOCAL_FILENAME, pkg_get_string(newpkg, PKG_LOCAL_FILENAME));
        if (!oldpkg->tmp_unpack_dir)
                oldpkg->tmp_unpack_dir = xstrdup(newpkg->tmp_unpack_dir);
-       if (!oldpkg->md5sum)
-               oldpkg->md5sum = xstrdup(newpkg->md5sum);
-#if defined HAVE_SHA256
-       if (!oldpkg->sha256sum)
-               oldpkg->sha256sum = xstrdup(newpkg->sha256sum);
-#endif
+       if (!pkg_get_string(oldpkg, PKG_MD5SUM))
+               pkg_set_string(oldpkg, PKG_MD5SUM, pkg_get_string(newpkg, PKG_MD5SUM));
+       if (!pkg_get_string(oldpkg, PKG_SHA256SUM))
+               pkg_set_string(oldpkg, PKG_SHA256SUM, pkg_get_string(newpkg, PKG_SHA256SUM));
        if (!oldpkg->size)
                oldpkg->size = newpkg->size;
        if (!oldpkg->installed_size)
                oldpkg->installed_size = newpkg->installed_size;
-       if (!oldpkg->priority)
-               oldpkg->priority = xstrdup(newpkg->priority);
-       if (!oldpkg->source)
-               oldpkg->source = xstrdup(newpkg->source);
+       if (!pkg_get_string(oldpkg, PKG_PRIORITY))
+               pkg_set_string(oldpkg, PKG_PRIORITY, pkg_get_string(newpkg, PKG_PRIORITY));
+       if (!pkg_get_string(oldpkg, PKG_SOURCE))
+               pkg_set_string(oldpkg, PKG_SOURCE, pkg_get_string(newpkg, PKG_SOURCE));
 
        if (nv_pair_list_empty(&oldpkg->conffiles)) {
                list_splice_init(&newpkg->conffiles.head,
@@ -593,6 +586,7 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
 {
        int i, j;
        char *str;
+       const char *p;
        int depends_count = pkg->pre_depends_count +
            pkg->depends_count + pkg->recommends_count + pkg->suggests_count;
 
@@ -604,9 +598,10 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
        case 'a':
        case 'A':
                if (strcasecmp(field, "Architecture") == 0) {
-                       if (pkg->architecture) {
+                       p = pkg_get_string(pkg, PKG_ARCHITECTURE);
+                       if (p) {
                                fprintf(fp, "Architecture: %s\n",
-                                       pkg->architecture);
+                                       p);
                        }
                } else if (strcasecmp(field, "Auto-Installed") == 0) {
                        if (pkg->auto_installed)
@@ -674,9 +669,10 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
                                fprintf(fp, "\n");
                        }
                } else if (strcasecmp(field, "Description") == 0) {
-                       if (pkg->description) {
+                       p = pkg_get_string(pkg, PKG_DESCRIPTION);
+                       if (p) {
                                fprintf(fp, "Description: %s\n",
-                                       pkg->description);
+                                       p);
                        }
                } else {
                        goto UNKNOWN_FMT_FIELD;
@@ -690,8 +686,9 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
                break;
        case 'f':
        case 'F':
-               if (pkg->filename) {
-                       fprintf(fp, "Filename: %s\n", pkg->filename);
+               p = pkg_get_string(pkg, PKG_FILENAME);
+               if (p) {
+                       fprintf(fp, "Filename: %s\n", p);
                }
                break;
        case 'i':
@@ -708,13 +705,14 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
        case 'm':
        case 'M':
                if (strcasecmp(field, "Maintainer") == 0) {
-                       if (pkg->maintainer) {
-                               fprintf(fp, "Maintainer: %s\n",
-                                       pkg->maintainer);
+                       p = pkg_get_string(pkg, PKG_MAINTAINER);
+                       if (p) {
+                               fprintf(fp, "Maintainer: %s\n", p);
                        }
                } else if (strcasecmp(field, "MD5sum") == 0) {
-                       if (pkg->md5sum) {
-                               fprintf(fp, "MD5Sum: %s\n", pkg->md5sum);
+                       p = pkg_get_string(pkg, PKG_MD5SUM);
+                       if (p) {
+                               fprintf(fp, "MD5Sum: %s\n", p);
                        }
                } else {
                        goto UNKNOWN_FMT_FIELD;
@@ -725,7 +723,7 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
                if (strcasecmp(field, "Package") == 0) {
                        fprintf(fp, "Package: %s\n", pkg->name);
                } else if (strcasecmp(field, "Priority") == 0) {
-                       fprintf(fp, "Priority: %s\n", pkg->priority);
+                       fprintf(fp, "Priority: %s\n", pkg_get_string(pkg, PKG_PRIORITY));
                } else if (strcasecmp(field, "Provides") == 0) {
                        if (pkg->provides_count > 1) {
                                fprintf(fp, "Provides:");
@@ -771,13 +769,15 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
        case 's':
        case 'S':
                if (strcasecmp(field, "Section") == 0) {
-                       if (pkg->section) {
-                               fprintf(fp, "Section: %s\n", pkg->section);
+                       p = pkg_get_string(pkg, PKG_SECTION);
+                       if (p) {
+                               fprintf(fp, "Section: %s\n", p);
                        }
 #if defined HAVE_SHA256
                } else if (strcasecmp(field, "SHA256sum") == 0) {
-                       if (pkg->sha256sum) {
-                               fprintf(fp, "SHA256sum: %s\n", pkg->sha256sum);
+                       p = pkg_get_string(pkg, PKG_SHA256SUM);
+                       if (p) {
+                               fprintf(fp, "SHA256sum: %s\n", p);
                        }
 #endif
                } else if (strcasecmp(field, "Size") == 0) {
@@ -785,8 +785,9 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
                                fprintf(fp, "Size: %ld\n", pkg->size);
                        }
                } else if (strcasecmp(field, "Source") == 0) {
-                       if (pkg->source) {
-                               fprintf(fp, "Source: %s\n", pkg->source);
+                       p = pkg_get_string(pkg, PKG_SOURCE);
+                       if (p) {
+                               fprintf(fp, "Source: %s\n", p);
                        }
                } else if (strcasecmp(field, "Status") == 0) {
                        char *pflag = pkg_state_flag_to_str(pkg->state_flag);
@@ -816,8 +817,9 @@ void pkg_formatted_field(FILE * fp, pkg_t * pkg, const char *field)
        case 't':
        case 'T':
                if (strcasecmp(field, "Tags") == 0) {
-                       if (pkg->tags) {
-                               fprintf(fp, "Tags: %s\n", pkg->tags);
+                       p = pkg_get_string(pkg, PKG_TAGS);
+                       if (p) {
+                               fprintf(fp, "Tags: %s\n", p);
                        }
                }
                break;
@@ -944,22 +946,28 @@ static int verrevcmp(const char *val, const char *ref)
 
 int pkg_compare_versions(const pkg_t * pkg, const pkg_t * ref_pkg)
 {
+       unsigned int epoch1 = (unsigned int) pkg_get_int(pkg, PKG_EPOCH);
+       unsigned int epoch2 = (unsigned int) pkg_get_int(ref_pkg, PKG_EPOCH);
+       char *revision1 = pkg_get_ptr(pkg, PKG_REVISION);
+       char *revision2 = pkg_get_ptr(ref_pkg, PKG_REVISION);
+       const char *version1 = pkg_get_string(pkg, PKG_VERSION);
+       const char *version2 = pkg_get_string(ref_pkg, PKG_VERSION);
        int r;
 
-       if (pkg->epoch > ref_pkg->epoch) {
+       if (epoch1 > epoch2) {
                return 1;
        }
 
-       if (pkg->epoch < ref_pkg->epoch) {
+       if (epoch1 < epoch2) {
                return -1;
        }
 
-       r = verrevcmp(pkg->version, ref_pkg->version);
+       r = verrevcmp(version1, version2);
        if (r) {
                return r;
        }
 
-       r = verrevcmp(pkg->revision, ref_pkg->revision);
+       r = verrevcmp(revision1, revision2);
        if (r) {
                return r;
        }
@@ -999,8 +1007,8 @@ int pkg_version_satisfied(pkg_t * it, pkg_t * ref, const char *op)
 
 int pkg_name_version_and_architecture_compare(const void *p1, const void *p2)
 {
-       const pkg_t *a = *(const pkg_t **)p1;
-       const pkg_t *b = *(const pkg_t **)p2;
+       const pkg_t * a = *(const pkg_t **)p1;
+       const pkg_t * b = *(const pkg_t **)p2;
        int namecmp;
        int vercmp;
        if (!a->name || !b->name) {
@@ -1042,21 +1050,26 @@ int abstract_pkg_name_compare(const void *p1, const void *p2)
 
 char *pkg_version_str_alloc(pkg_t * pkg)
 {
-       char *version;
+       const char *verstr;
+       char *version, *revptr;
+       unsigned int epoch = (unsigned int) pkg_get_int(pkg, PKG_EPOCH);
+
+       revptr = pkg_get_ptr(pkg, PKG_REVISION);
+       verstr = pkg_get_string(pkg, PKG_VERSION);
 
-       if (pkg->epoch) {
-               if (pkg->revision)
+       if (epoch) {
+               if (revptr)
                        sprintf_alloc(&version, "%d:%s-%s",
-                                     pkg->epoch, pkg->version, pkg->revision);
+                                     epoch, verstr, revptr);
                else
                        sprintf_alloc(&version, "%d:%s",
-                                     pkg->epoch, pkg->version);
+                                     epoch, verstr);
        } else {
-               if (pkg->revision)
+               if (revptr)
                        sprintf_alloc(&version, "%s-%s",
-                                     pkg->version, pkg->revision);
+                                     verstr, revptr);
                else
-                       version = xstrdup(pkg->version);
+                       version = xstrdup(verstr);
        }
 
        return version;
@@ -1074,6 +1087,7 @@ str_list_t *pkg_get_installed_files(pkg_t * pkg)
        char *installed_file_name;
        unsigned int rootdirlen = 0;
        int list_from_package;
+       const char *local_filename;
 
        pkg->installed_files_ref_cnt++;
 
@@ -1093,7 +1107,9 @@ str_list_t *pkg_get_installed_files(pkg_t * pkg)
                list_from_package = 0;
 
        if (list_from_package) {
-               if (pkg->local_filename == NULL) {
+               local_filename = pkg_get_string(pkg, PKG_LOCAL_FILENAME);
+
+               if (!local_filename) {
                        return pkg->installed_files;
                }
                /* XXX: CLEANUP: Maybe rewrite this to avoid using a temporary
@@ -1121,7 +1137,7 @@ str_list_t *pkg_get_installed_files(pkg_t * pkg)
                err = pkg_extract_data_file_names_to_stream(pkg, list_file);
                if (err) {
                        opkg_msg(ERROR, "Error extracting file list from %s.\n",
-                                pkg->local_filename);
+                                local_filename);
                        fclose(list_file);
                        unlink(list_file_name);
                        free(list_file_name);
@@ -1318,13 +1334,14 @@ int pkg_run_script(pkg_t * pkg, const char *script, const char *args)
 int pkg_arch_supported(pkg_t * pkg)
 {
        nv_pair_list_elt_t *l;
+       char *architecture = pkg_get_string(pkg, PKG_ARCHITECTURE);
 
-       if (!pkg->architecture)
+       if (!architecture)
                return 1;
 
        list_for_each_entry(l, &conf->arch_list.head, node) {
                nv_pair_t *nv = (nv_pair_t *) l->data;
-               if (strcmp(nv->name, pkg->architecture) == 0) {
+               if (strcmp(nv->name, architecture) == 0) {
                        opkg_msg(DEBUG,
                                 "Arch %s (priority %s) supported for pkg %s.\n",
                                 nv->name, nv->value, pkg->name);
@@ -1333,7 +1350,7 @@ int pkg_arch_supported(pkg_t * pkg)
        }
 
        opkg_msg(DEBUG, "Arch %s unsupported for pkg %s.\n",
-                pkg->architecture, pkg->name);
+                architecture, pkg->name);
        return 0;
 }
 
index 15f580c..6e09f0a 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 
 #include <sys/types.h>
+#include <libubox/blob.h>
 
 #include "pkg_vec.h"
 #include "str_list.h"
@@ -32,7 +33,9 @@
 
 struct opkg_conf;
 
+#ifndef ARRAY_SIZE
 #define ARRAY_SIZE(array) sizeof(array) / sizeof((array)[0])
+#endif
 
 /* I think "Size" is currently the shortest field name */
 #define PKG_MINIMUM_FIELD_NAME_LEN 4
@@ -75,6 +78,23 @@ enum pkg_state_status {
 };
 typedef enum pkg_state_status pkg_state_status_t;
 
+enum pkg_fields {
+       PKG_MAINTAINER,
+       PKG_PRIORITY,
+       PKG_SOURCE,
+       PKG_TAGS,
+       PKG_SECTION,
+       PKG_EPOCH,
+       PKG_FILENAME,
+       PKG_LOCAL_FILENAME,
+       PKG_VERSION,
+       PKG_REVISION,
+       PKG_ARCHITECTURE,
+       PKG_DESCRIPTION,
+       PKG_MD5SUM,
+       PKG_SHA256SUM,
+};
+
 struct abstract_pkg {
        char *name;
        int dependencies_checked;
@@ -113,16 +133,8 @@ struct abstract_pkg {
    we don't often free them.  */
 struct pkg {
        char *name;
-       unsigned long epoch;
-       char *version;
-       char *revision;
        pkg_src_t *src;
        pkg_dest_t *dest;
-       char *architecture;
-       char *section;
-       char *maintainer;
-       char *description;
-       char *tags;
        pkg_state_want_t state_want;
        pkg_state_flag_t state_flag;
        pkg_state_status_t state_status;
@@ -151,17 +163,9 @@ struct pkg {
 
        abstract_pkg_t *parent;
 
-       char *filename;
-       char *local_filename;
        char *tmp_unpack_dir;
-       char *md5sum;
-#if defined HAVE_SHA256
-       char *sha256sum;
-#endif
        unsigned long size;     /* in bytes */
        unsigned long installed_size;   /* in bytes */
-       char *priority;
-       char *source;
        conffile_list_t conffiles;
        time_t installed_time;
        /* As pointer for lazy evaluation */
@@ -181,11 +185,44 @@ struct pkg {
         * package's dependancies */
        int auto_installed:1;
        int is_upgrade:1;
+
+       struct blob_buf blob;
 };
 
 pkg_t *pkg_new(void);
 void pkg_deinit(pkg_t * pkg);
 int pkg_init_from_file(pkg_t * pkg, const char *filename);
+
+void *pkg_set_raw(pkg_t *pkg, int id, const void *val, size_t len);
+void *pkg_get_raw(const pkg_t *pkg, int id);
+
+static inline int pkg_set_int(pkg_t *pkg, int id, int val)
+{
+       return (intptr_t) pkg_set_raw(pkg, id, &val, sizeof(val));
+}
+
+static inline int pkg_get_int(const pkg_t *pkg, int id)
+{
+       return (intptr_t) pkg_get_raw(pkg, id);
+}
+
+char *pkg_set_string(pkg_t *pkg, int id, const char *s);
+
+static inline char *pkg_get_string(const pkg_t *pkg, int id)
+{
+       return (char *) pkg_get_raw(pkg, id);
+}
+
+static inline void * pkg_set_ptr(pkg_t *pkg, int id, void *ptr)
+{
+       return pkg_set_raw(pkg, id, ptr, sizeof(ptr));
+}
+
+static inline void * pkg_get_ptr(const pkg_t *pkg, int id)
+{
+       return pkg_get_raw(pkg, id);
+}
+
 abstract_pkg_t *abstract_pkg_new(void);
 
 /*
@@ -196,7 +233,7 @@ int pkg_merge(pkg_t * oldpkg, pkg_t * newpkg);
 
 char *pkg_version_str_alloc(pkg_t * pkg);
 
-int pkg_compare_versions(const pkg_t * pkg, const pkg_t * ref_pkg);
+int pkg_compare_versions(const pkg_t *pkg, const pkg_t *ref_pkg);
 int pkg_name_version_and_architecture_compare(const void *a, const void *b);
 int abstract_pkg_name_compare(const void *a, const void *b);
 
index 70c2922..d741c4a 100644 (file)
@@ -441,7 +441,7 @@ int version_constraints_satisfied(depend_t * depends, pkg_t * pkg)
 
        comparison = pkg_compare_versions(pkg, temp);
 
-       free(temp->version);
+       pkg_deinit(temp);
        free(temp);
 
        if ((depends->constraint == EARLIER) && (comparison < 0))
@@ -516,14 +516,18 @@ int pkg_dependence_satisfied(depend_t * depend)
 static int is_pkg_in_pkg_vec(pkg_vec_t * vec, pkg_t * pkg)
 {
        int i;
+       char *arch1, *arch2;
        pkg_t **pkgs = vec->pkgs;
+       arch1 = pkg_get_string(pkg, PKG_ARCHITECTURE);
+
+       for (i = 0; i < vec->len; i++) {
+               arch2 = pkg_get_string(*(pkgs + i), PKG_ARCHITECTURE);
 
-       for (i = 0; i < vec->len; i++)
                if ((strcmp(pkg->name, (*(pkgs + i))->name) == 0)
                    && (pkg_compare_versions(pkg, *(pkgs + i)) == 0)
-                   && (strcmp(pkg->architecture, (*(pkgs + i))->architecture)
-                       == 0))
+                   && (strcmp(arch1, arch2) == 0))
                        return 1;
+       }
        return 0;
 }
 
index 8a541e3..6259521 100644 (file)
@@ -25,7 +25,7 @@
 int pkg_extract_control_file_to_stream(pkg_t * pkg, FILE * stream)
 {
        int err;
-       deb_extract(pkg->local_filename, stream,
+       deb_extract(pkg_get_string(pkg, PKG_LOCAL_FILENAME), stream,
                    extract_control_tar_gz
                    | extract_to_stream, NULL, "control", &err);
        return err;
@@ -40,7 +40,7 @@ pkg_extract_control_files_to_dir_with_prefix(pkg_t * pkg, const char *dir,
 
        sprintf_alloc(&dir_with_prefix, "%s/%s", dir, prefix);
 
-       deb_extract(pkg->local_filename, stderr,
+       deb_extract(pkg_get_string(pkg, PKG_LOCAL_FILENAME), stderr,
                    extract_control_tar_gz
                    | extract_all_to_fs | extract_preserve_date
                    | extract_unconditional, dir_with_prefix, NULL, &err);
@@ -58,7 +58,7 @@ int pkg_extract_data_files_to_dir(pkg_t * pkg, const char *dir)
 {
        int err;
 
-       deb_extract(pkg->local_filename, stderr,
+       deb_extract(pkg_get_string(pkg, PKG_LOCAL_FILENAME), stderr,
                    extract_data_tar_gz
                    | extract_all_to_fs | extract_preserve_date
                    | extract_unconditional, dir, NULL, &err);
@@ -83,7 +83,7 @@ int pkg_extract_data_file_names_to_stream(pkg_t * pkg, FILE * stream)
           right here, by writing to a tmpfile, then munging things as we
           wrote to the actual stream. */
 
-       deb_extract(pkg->local_filename, stream,
+       deb_extract(pkg_get_string(pkg, PKG_LOCAL_FILENAME), stream,
                    extract_quiet | extract_data_tar_gz | extract_list,
                    NULL, NULL, &err);
 
index edc5188..1b3fd05 100644 (file)
@@ -141,7 +141,7 @@ pkg_hash_add_from_file(const char *file_name,
                        continue;
                }
 
-               if (!pkg->architecture || !pkg->arch_priority) {
+               if (!pkg_get_string(pkg, PKG_ARCHITECTURE) || !pkg->arch_priority) {
                        char *version_str = pkg_version_str_alloc(pkg);
                        opkg_msg(NOTICE, "Package %s version %s has no "
                                 "valid architecture, ignoring.\n",
@@ -319,8 +319,8 @@ pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg,
                                pkg_t *maybe = vec->pkgs[j];
                                opkg_msg(DEBUG,
                                         "%s arch=%s arch_priority=%d version=%s.\n",
-                                        maybe->name, maybe->architecture,
-                                        maybe->arch_priority, maybe->version);
+                                        maybe->name, pkg_get_string(maybe, PKG_ARCHITECTURE),
+                                        maybe->arch_priority, pkg_get_string(maybe, PKG_VERSION));
                                /* We make sure not to add the same package twice. Need to search for the reason why
                                   they show up twice sometimes. */
                                if ((maybe->arch_priority > 0)
@@ -359,7 +359,7 @@ pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg,
                pkg_t *matching = matching_pkgs->pkgs[i];
                if (constraint_fcn(matching, cdata)) {
                        opkg_msg(DEBUG, "Candidate: %s %s.\n",
-                                matching->name, matching->version);
+                                matching->name, pkg_get_string(matching, PKG_VERSION));
                        good_pkg_by_name = matching;
                        /* It has been provided by hand, so it is what user want */
                        if (matching->provided_by_hand == 1)
@@ -405,8 +405,8 @@ pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg,
                for (i = 0; i < matching_pkgs->len; i++) {
                        pkg_t *matching = matching_pkgs->pkgs[i];
                        opkg_msg(INFO, "%s %s %s\n",
-                                matching->name, matching->version,
-                                matching->architecture);
+                                matching->name, pkg_get_string(matching, PKG_VERSION),
+                                pkg_get_string(matching, PKG_ARCHITECTURE));
                }
        }
 
@@ -431,8 +431,8 @@ pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg,
        }
        if (priorized_matching) {
                opkg_msg(INFO, "Using priorized matching %s %s %s.\n",
-                        priorized_matching->name, priorized_matching->version,
-                        priorized_matching->architecture);
+                        priorized_matching->name, pkg_get_string(priorized_matching, PKG_VERSION),
+                        pkg_get_string(priorized_matching, PKG_ARCHITECTURE));
                return priorized_matching;
        }
        if (nmatching > 1) {
@@ -442,8 +442,8 @@ pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg,
        }
        if (latest_matching) {
                opkg_msg(INFO, "Using latest matching %s %s %s.\n",
-                        latest_matching->name, latest_matching->version,
-                        latest_matching->architecture);
+                        latest_matching->name, pkg_get_string(latest_matching, PKG_VERSION),
+                        pkg_get_string(latest_matching, PKG_ARCHITECTURE));
                return latest_matching;
        }
        return NULL;
index f9da0cc..b7b2fe3 100644 (file)
@@ -59,7 +59,7 @@ static void parse_conffiles(pkg_t * pkg, const char *cstr)
 
 int parse_version(pkg_t * pkg, const char *vstr)
 {
-       char *colon;
+       char *colon, *rev;
 
        if (strncmp(vstr, "Version:", 8) == 0)
                vstr += 8;
@@ -70,20 +70,19 @@ int parse_version(pkg_t * pkg, const char *vstr)
        colon = strchr(vstr, ':');
        if (colon) {
                errno = 0;
-               pkg->epoch = strtoul(vstr, NULL, 10);
+               pkg_set_int(pkg, PKG_EPOCH, strtoul(vstr, NULL, 10));
                if (errno) {
                        opkg_perror(ERROR, "%s: invalid epoch", pkg->name);
                }
                vstr = ++colon;
-       } else {
-               pkg->epoch = 0;
        }
 
-       pkg->version = xstrdup(vstr);
-       pkg->revision = strrchr(pkg->version, '-');
+       rev = strrchr(pkg_set_string(pkg, PKG_VERSION, vstr), '-');
 
-       if (pkg->revision)
-               *pkg->revision++ = '\0';
+       if (rev) {
+               *rev++ = '\0';
+               pkg_set_ptr(pkg, PKG_REVISION, rev);
+       }
 
        return 0;
 }
@@ -106,6 +105,7 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
 
        /* these flags are a bit hackish... */
        static int reading_conffiles = 0, reading_description = 0;
+       static char *description = NULL;
        int ret = 0;
 
        /* Exclude globally masked fields. */
@@ -117,9 +117,9 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
        switch (*line) {
        case 'A':
                if ((mask & PFM_ARCHITECTURE) && is_field("Architecture", line)) {
-                       pkg->architecture = parse_simple("Architecture", line);
-                       pkg->arch_priority =
-                           get_arch_priority(pkg->architecture);
+                       pkg->arch_priority = get_arch_priority(
+                               pkg_set_string(pkg, PKG_ARCHITECTURE, line + strlen("Architecture") + 1));
+
                } else if ((mask & PFM_AUTO_INSTALLED)
                           && is_field("Auto-Installed", line)) {
                        char *tmp = parse_simple("Auto-Installed", line);
@@ -142,7 +142,7 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
 
        case 'D':
                if ((mask & PFM_DESCRIPTION) && is_field("Description", line)) {
-                       pkg->description = parse_simple("Description", line);
+                       description = parse_simple("Description", line);
                        reading_conffiles = 0;
                        reading_description = 1;
                        goto dont_reset_flags;
@@ -162,7 +162,7 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
 
        case 'F':
                if ((mask & PFM_FILENAME) && is_field("Filename", line))
-                       pkg->filename = parse_simple("Filename", line);
+                       pkg_set_string(pkg, PKG_FILENAME, line + strlen("Filename") + 1);
                break;
 
        case 'I':
@@ -181,21 +181,21 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
 
        case 'M':
                if ((mask & PFM_MD5SUM) && is_field("MD5sum:", line))
-                       pkg->md5sum = parse_simple("MD5sum", line);
+                       pkg_set_string(pkg, PKG_MD5SUM, line + strlen("MD5sum") + 1);
                /* The old opkg wrote out status files with the wrong
                 * case for MD5sum, let's parse it either way */
                else if ((mask & PFM_MD5SUM) && is_field("MD5Sum:", line))
-                       pkg->md5sum = parse_simple("MD5Sum", line);
+                       pkg_set_string(pkg, PKG_MD5SUM, line + strlen("MD5Sum") + 1);
                else if ((mask & PFM_MAINTAINER)
                         && is_field("Maintainer", line))
-                       pkg->maintainer = parse_simple("Maintainer", line);
+                       pkg_set_string(pkg, PKG_MAINTAINER, line + strlen("Maintainer") + 1);
                break;
 
        case 'P':
                if ((mask & PFM_PACKAGE) && is_field("Package", line))
                        pkg->name = parse_simple("Package", line);
                else if ((mask & PFM_PRIORITY) && is_field("Priority", line))
-                       pkg->priority = parse_simple("Priority", line);
+                       pkg_set_string(pkg, PKG_PRIORITY, line + strlen("Priority") + 1);
                else if ((mask & PFM_PROVIDES) && is_field("Provides", line))
                        pkg->provides_str =
                            parse_list(line, &pkg->provides_count, ',', 0);
@@ -217,17 +217,17 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
 
        case 'S':
                if ((mask & PFM_SECTION) && is_field("Section", line))
-                       pkg->section = parse_simple("Section", line);
+                       pkg_set_string(pkg, PKG_SECTION, line + strlen("Section") + 1);
 #ifdef HAVE_SHA256
                else if ((mask & PFM_SHA256SUM) && is_field("SHA256sum", line))
-                       pkg->sha256sum = parse_simple("SHA256sum", line);
+                       pkg_set_string(pkg, PKG_SHA256SUM, line + strlen("SHA256sum") + 1);
 #endif
                else if ((mask & PFM_SIZE) && is_field("Size", line)) {
                        char *tmp = parse_simple("Size", line);
                        pkg->size = strtoul(tmp, NULL, 0);
                        free(tmp);
                } else if ((mask & PFM_SOURCE) && is_field("Source", line))
-                       pkg->source = parse_simple("Source", line);
+                       pkg_set_string(pkg, PKG_SOURCE, line + strlen("Source") + 1);
                else if ((mask & PFM_STATUS) && is_field("Status", line))
                        parse_status(pkg, line);
                else if ((mask & PFM_SUGGESTS) && is_field("Suggests", line))
@@ -237,7 +237,7 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
 
        case 'T':
                if ((mask & PFM_TAGS) && is_field("Tags", line))
-                       pkg->tags = parse_simple("Tags", line);
+                       pkg_set_string(pkg, PKG_TAGS, line + strlen("Tags") + 1);
                break;
 
        case 'V':
@@ -248,19 +248,17 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
        case ' ':
                if ((mask & PFM_DESCRIPTION) && reading_description) {
                        if (isatty(1)) {
-                               pkg->description = xrealloc(pkg->description,
-                                                           strlen(pkg->
-                                                                  description)
+                               description = xrealloc(description,
+                                                           strlen(description)
                                                            + 1 + strlen(line) +
                                                            1);
-                               strcat(pkg->description, "\n");
+                               strcat(description, "\n");
                        } else {
-                               pkg->description = xrealloc(pkg->description,
-                                                           strlen(pkg->
-                                                                  description)
+                               description = xrealloc(description,
+                                                           strlen(description)
                                                            + 1 + strlen(line));
                        }
-                       strcat(pkg->description, (line));
+                       strcat(description, (line));
                        goto dont_reset_flags;
                } else if ((mask & PFM_CONFFILES) && reading_conffiles) {
                        parse_conffiles(pkg, line);
@@ -276,7 +274,13 @@ int pkg_parse_line(void *ptr, const char *line, uint mask)
                }
        }
 
-       reading_description = 0;
+       if (reading_description && description) {
+               pkg_set_string(pkg, PKG_DESCRIPTION, description);
+               free(description);
+               reading_description = 0;
+               description = NULL;
+       }
+
        reading_conffiles = 0;
 
 dont_reset_flags:
index 162c70f..d37a185 100644 (file)
@@ -52,27 +52,29 @@ void pkg_vec_insert_merge(pkg_vec_t * vec, pkg_t * pkg, int set_status)
 {
        int i;
        int found = 0;
+       char *pkg_version = pkg_get_string(pkg, PKG_VERSION);
+       char *pkg_architecture = pkg_get_string(pkg, PKG_ARCHITECTURE);
+       char *vec_architecture;
 
        /* look for a duplicate pkg by name, version, and architecture */
        for (i = 0; i < vec->len; i++) {
+               vec_architecture = pkg_get_string(vec->pkgs[i], PKG_ARCHITECTURE);
+
                opkg_msg(DEBUG2, "%s %s arch=%s vs. %s %s arch=%s.\n",
-                        pkg->name, pkg->version, pkg->architecture,
-                        vec->pkgs[i]->name, vec->pkgs[i]->version,
-                        vec->pkgs[i]->architecture);
+                        pkg->name, pkg_version, pkg_architecture,
+                        vec->pkgs[i]->name, pkg_get_string(vec->pkgs[i], PKG_VERSION),
+                        vec_architecture);
                /* if the name,ver,arch matches, or the name matches and the
                 * package is marked deinstall/hold  */
                if ((!strcmp(pkg->name, vec->pkgs[i]->name))
                    && ((pkg->state_want == SW_DEINSTALL
                         && (pkg->state_flag & SF_HOLD))
                        || ((pkg_compare_versions(pkg, vec->pkgs[i]) == 0)
-                           &&
-                           (!strcmp
-                            (pkg->architecture,
-                             vec->pkgs[i]->architecture))))) {
+                           && (!strcmp(pkg_architecture, vec_architecture))))) {
                        found = 1;
                        opkg_msg(DEBUG2,
                                 "Duplicate for pkg=%s version=%s arch=%s.\n",
-                                pkg->name, pkg->version, pkg->architecture);
+                                pkg->name, pkg_version, pkg_architecture);
                        break;
                }
        }
@@ -80,14 +82,14 @@ void pkg_vec_insert_merge(pkg_vec_t * vec, pkg_t * pkg, int set_status)
        /* we didn't find one, add it */
        if (!found) {
                opkg_msg(DEBUG2, "Adding new pkg=%s version=%s arch=%s.\n",
-                        pkg->name, pkg->version, pkg->architecture);
+                        pkg->name, pkg_version, pkg_architecture);
                pkg_vec_insert(vec, pkg);
                return;
        }
 
        /* update the one that we have */
        opkg_msg(DEBUG2, "Merging %s %s arch=%s, set_status=%d.\n",
-                pkg->name, pkg->version, pkg->architecture, set_status);
+                pkg->name, pkg_version, pkg_architecture, set_status);
        if (set_status) {
                /* This is from the status file,
                 * so need to merge with existing database */
index 86c9db7..aa48bef 100644 (file)
@@ -3,4 +3,4 @@ bin_PROGRAMS = opkg-cl
 
 opkg_cl_SOURCES = opkg-cl.c
 opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.a \
-                $(top_builddir)/libbb/libbb.a $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS) -lpthread
+                $(top_builddir)/libbb/libbb.a $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS) -lpthread -lubox
index dc8c0fa..d1d26f7 100644 (file)
@@ -16,7 +16,7 @@ noinst_PROGRAMS = libopkg_test
 #opkg_active_list_test_SOURCES = opkg_active_list_test.c
 #opkg_active_list_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir)
 
-libopkg_test_LDADD = $(top_builddir)/libopkg/libopkg.a $(top_builddir)/libbb/libbb.a $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS) -lpthread
+libopkg_test_LDADD = $(top_builddir)/libopkg/libopkg.a $(top_builddir)/libbb/libbb.a $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS) -lpthread -lubox
 libopkg_test_SOURCE = libopkg_test.c
 libopkg_test_LDFLAGS = -static
 
index 3ed3b8b..78f68a6 100644 (file)
@@ -57,6 +57,8 @@ void package_list_upgradable_callback(pkg_t * pkg, void *data)
 void print_package(pkg_t * pkg)
 {
        char *v = pkg_version_str_alloc(pkg);
+       const char *tags = pkg_get_string(pkg, PKG_TAGS);
+
        printf("Name:         %s\n"
               "Version:      %s\n"
               "Repository:   %s\n"
@@ -68,9 +70,9 @@ void print_package(pkg_t * pkg)
               pkg->name,
               v,
               pkg->src->name,
-              pkg->architecture,
-              pkg->description,
-              pkg->tags ? pkg->tags : "", pkg->size, pkg->state_status);
+              pkg_get_string(pkg, PKG_ARCHITECTURE),
+              pkg_get_string(pkg, PKG_DESCRIPTION),
+              tags ? tags : "", pkg->size, pkg->state_status);
        free(v);
 }
 
@@ -88,8 +90,9 @@ void opkg_test(void)
        if (find_pkg) {
                printf("Finding package \"%s\"\n", find_pkg->name);
                pkg =
-                   opkg_find_package(find_pkg->name, find_pkg->version,
-                                     find_pkg->architecture,
+                   opkg_find_package(find_pkg->name,
+                                     pkg_get_string(find_pkg, PKG_VERSION),
+                                     pkg_get_string(find_pkg, PKG_ARCHITECTURE),
                                      find_pkg->src->name);
                if (pkg) {
                        print_package(pkg);