libopkg: support passing default state flags in pkg_hash_load_feeds()
[oweals/opkg-lede.git] / libopkg / opkg.c
index fdb2fe38284170f19277f5af6a6523719db77bf7..dc1148386ba18e63c80a531dd843e0d92cd6cd02 100644 (file)
@@ -43,8 +43,7 @@
 
 /** Private Functions ***/
 
-static int
-opkg_configure_packages(char *pkg_name)
+static int opkg_configure_packages(char *pkg_name)
 {
        pkg_vec_t *all;
        int i;
@@ -85,10 +84,9 @@ struct _curl_cb_data {
        int finish_range;
 };
 
-int
-curl_progress_cb(struct _curl_cb_data *cb_data, double t,      /* dltotal */
-               double d,       /* dlnow */
-               double ultotal, double ulnow)
+int curl_progress_cb(struct _curl_cb_data *cb_data, double t,  /* dltotal */
+                    double d,  /* dlnow */
+                    double ultotal, double ulnow)
 {
        int p = (t) ? d * 100 / t : 0;
        static int prev = -1;
@@ -111,16 +109,20 @@ curl_progress_cb(struct _curl_cb_data *cb_data, double t, /* dltotal */
        return 0;
 }
 
-
+static struct opkg_conf saved_conf;
 /*** Public API ***/
 
-int
-opkg_new()
+int opkg_new()
 {
+       saved_conf = *conf;
+
        if (opkg_conf_init())
                goto err0;
 
-       if (pkg_hash_load_feeds())
+       if (opkg_conf_load())
+               goto err0;
+
+       if (pkg_hash_load_feeds(0))
                goto err1;
 
        if (pkg_hash_load_status_files())
@@ -135,8 +137,7 @@ err0:
        return -1;
 }
 
-void
-opkg_free(void)
+void opkg_free(void)
 {
 #ifdef HAVE_CURL
        opkg_curl_cleanup();
@@ -144,27 +145,14 @@ opkg_free(void)
        opkg_conf_deinit();
 }
 
-int
-opkg_re_read_config_files(void)
+int opkg_re_read_config_files(void)
 {
-       pkg_hash_deinit();
-       pkg_hash_init();
-
-       if (pkg_hash_load_feeds())
-               goto err;
-
-       if (pkg_hash_load_status_files())
-               goto err;
-
-       return 0;
-
-err:
-       pkg_hash_deinit();
-       return -1;
+       opkg_free();
+       *conf = saved_conf;
+       return opkg_new();
 }
 
-void
-opkg_get_option(char *option, void **value)
+void opkg_get_option(char *option, void **value)
 {
        int i = 0;
        extern opkg_option_t options[];
@@ -182,22 +170,21 @@ opkg_get_option(char *option, void **value)
        /* get the option */
        switch (options[i].type) {
        case OPKG_OPT_TYPE_BOOL:
-               *((int *) value) = *((int *) options[i].value);
+               *((int *)value) = *((int *)options[i].value);
                return;
 
        case OPKG_OPT_TYPE_INT:
-               *((int *) value) = *((int *) options[i].value);
+               *((int *)value) = *((int *)options[i].value);
                return;
 
        case OPKG_OPT_TYPE_STRING:
-               *((char **) value) = xstrdup(options[i].value);
+               *((char **)value) = xstrdup(options[i].value);
                return;
        }
 
 }
 
-void
-opkg_set_option(char *option, void *value)
+void opkg_set_option(char *option, void *value)
 {
        int i = 0, found = 0;
        extern opkg_option_t options[];
@@ -224,18 +211,18 @@ opkg_set_option(char *option, void *value)
        /* set the option */
        switch (options[i].type) {
        case OPKG_OPT_TYPE_BOOL:
-               if (*((int *) value) == 0)
-                       *((int *) options[i].value) = 0;
+               if (*((int *)value) == 0)
+                       *((int *)options[i].value) = 0;
                else
-                       *((int *) options[i].value) = 1;
+                       *((int *)options[i].value) = 1;
                return;
 
        case OPKG_OPT_TYPE_INT:
-               *((int *) options[i].value) = *((int *) value);
+               *((int *)options[i].value) = *((int *)value);
                return;
 
        case OPKG_OPT_TYPE_STRING:
-               *((char **) options[i].value) = xstrdup(value);
+               *((char **)options[i].value) = xstrdup(value);
                return;
        }
 
@@ -244,32 +231,32 @@ opkg_set_option(char *option, void *value)
 /**
  * @brief libopkg API: Install package
  * @param package_name The name of package in which is going to install
- * @param progress_callback The callback function that report the status to caller. 
+ * @param progress_callback The callback function that report the status to caller.
  */
 int
 opkg_install_package(const char *package_name,
-               opkg_progress_callback_t progress_callback,
-               void *user_data)
+                    opkg_progress_callback_t progress_callback,
+                    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);
 
        /* ... */
        pkg_info_preinstall_check();
 
-
        /* check to ensure package is not already installed */
        old = pkg_hash_fetch_installed_by_name(package_name);
        if (old) {
                opkg_msg(ERROR, "Package %s is already installed\n",
-                               package_name);
+                        package_name);
                return -1;
        }
 
@@ -290,11 +277,11 @@ opkg_install_package(const char *package_name,
        deps = pkg_vec_alloc();
        /* this function does not return the original package, so we insert it later */
        ndepends = pkg_hash_fetch_unsatisfied_dependencies(new, deps,
-                       &unresolved);
+                                                          &unresolved);
        if (unresolved) {
                char **tmp = unresolved;
                opkg_msg(ERROR, "Couldn't satisfy the following dependencies"
-                              " for %s:\n", package_name);
+                        " for %s:\n", package_name);
                while (*tmp) {
                        opkg_msg(ERROR, "\t%s", *tmp);
                        free(*tmp);
@@ -316,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;
@@ -324,20 +311,24 @@ opkg_install_package(const char *package_name,
 
                if (pkg->src == NULL) {
                        opkg_msg(ERROR, "Package %s not available from any "
-                                       "configured src\n", package_name);
+                                "configured src\n", 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;
@@ -345,9 +336,9 @@ 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);
+                                   &cb_data, 0);
                free(url);
 
                if (err) {
@@ -366,7 +357,6 @@ opkg_install_package(const char *package_name,
        }
        pkg_vec_free(all);
 
-
        /* 75% of "install" progress is for downloading */
        pdata.pkg = new;
        pdata.action = OPKG_INSTALL;
@@ -397,7 +387,7 @@ opkg_install_package(const char *package_name,
 
 int
 opkg_remove_package(const char *package_name,
-               opkg_progress_callback_t progress_callback, void *user_data)
+                   opkg_progress_callback_t progress_callback, void *user_data)
 {
        int err;
        pkg_t *pkg = NULL;
@@ -421,12 +411,12 @@ opkg_remove_package(const char *package_name,
 
        if (conf->restrict_to_default_dest) {
                pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(pkg->name,
-                                                     conf->default_dest);
+                                                                     conf->
+                                                                     default_dest);
        } else {
                pkg_to_remove = pkg_hash_fetch_installed_by_name(pkg->name);
        }
 
-
        progress(pdata, 75);
 
        err = opkg_remove_pkg(pkg_to_remove, 0);
@@ -435,15 +425,14 @@ opkg_remove_package(const char *package_name,
        opkg_conf_write_status_files();
        pkg_write_changed_filelists();
 
-
        progress(pdata, 100);
        return (err) ? -1 : 0;
 }
 
 int
 opkg_upgrade_package(const char *package_name,
-               opkg_progress_callback_t progress_callback,
-               void *user_data)
+                    opkg_progress_callback_t progress_callback,
+                    void *user_data)
 {
        int err;
        pkg_t *pkg;
@@ -523,6 +512,10 @@ opkg_upgrade_all(opkg_progress_callback_t progress_callback, void *user_data)
        if (err)
                return 1;
 
+       /* write out status files and file lists */
+       opkg_conf_write_status_files();
+       pkg_write_changed_filelists();
+
        pdata.pkg = NULL;
        progress(pdata, 100);
        return 0;
@@ -530,7 +523,7 @@ opkg_upgrade_all(opkg_progress_callback_t progress_callback, void *user_data)
 
 int
 opkg_update_package_lists(opkg_progress_callback_t progress_callback,
-                       void *user_data)
+                         void *user_data)
 {
        char *tmp;
        int err, result = 0;
@@ -545,7 +538,7 @@ opkg_update_package_lists(opkg_progress_callback_t progress_callback,
        progress(pdata, 0);
 
        sprintf_alloc(&lists_dir, "%s", (conf->restrict_to_default_dest)
-               ? conf->default_dest->lists_dir : conf->lists_dir);
+                     ? conf->default_dest->lists_dir : conf->lists_dir);
 
        if (!file_is_dir(lists_dir)) {
                if (file_exists(lists_dir)) {
@@ -557,7 +550,7 @@ opkg_update_package_lists(opkg_progress_callback_t progress_callback,
                err = file_mkdir_hier(lists_dir, 0755);
                if (err) {
                        opkg_msg(ERROR, "Couldn't create lists_dir %s\n",
-                                       lists_dir);
+                                lists_dir);
                        free(lists_dir);
                        return 1;
                }
@@ -566,7 +559,7 @@ opkg_update_package_lists(opkg_progress_callback_t progress_callback,
        sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
        if (mkdtemp(tmp) == NULL) {
                opkg_perror(ERROR, "Coundn't create temporary directory %s",
-                               tmp);
+                           tmp);
                free(lists_dir);
                free(tmp);
                return 1;
@@ -593,55 +586,14 @@ opkg_update_package_lists(opkg_progress_callback_t progress_callback,
                                      src->gzip ? "Packages.gz" : "Packages");
 
                sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
-               if (src->gzip) {
-                       FILE *in, *out;
-                       struct _curl_cb_data cb_data;
-                       char *tmp_file_name = NULL;
-
-                       sprintf_alloc(&tmp_file_name, "%s/%s.gz", tmp,
-                                     src->name);
-
-                       opkg_msg(INFO, "Downloading %s to %s...\n", url,
-                                       tmp_file_name);
-
-                       cb_data.cb = progress_callback;
-                       cb_data.progress_data = &pdata;
-                       cb_data.user_data = user_data;
-                       cb_data.start_range =
-                           100 * sources_done / sources_list_count;
-                       cb_data.finish_range =
-                           100 * (sources_done + 1) / sources_list_count;
-
-                       err = opkg_download(url, tmp_file_name,
-                                         (curl_progress_func) curl_progress_cb,
-                                         &cb_data);
-
-                       if (err == 0) {
-                               opkg_msg(INFO, "Inflating %s...\n",
-                                               tmp_file_name);
-                               in = fopen(tmp_file_name, "r");
-                               out = fopen(list_file_name, "w");
-                               if (in && out)
-                                       unzip(in, out);
-                               else
-                                       err = 1;
-                               if (in)
-                                       fclose(in);
-                               if (out)
-                                       fclose(out);
-                               unlink(tmp_file_name);
-                       }
-                       free(tmp_file_name);
-               } else
-                       err = opkg_download(url, list_file_name, NULL, NULL);
 
-               if (err) {
+               if (opkg_download(url, list_file_name, NULL, NULL, 0)) {
                        opkg_msg(ERROR, "Couldn't retrieve %s\n", url);
                        result = -1;
                }
                free(url);
 
-#if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
+#if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN)
                if (conf->check_signature) {
                        char *sig_file_name;
                        /* download detached signitures to verify the package lists */
@@ -660,32 +612,32 @@ opkg_update_package_lists(opkg_progress_callback_t progress_callback,
                        /* make sure there is no existing signature file */
                        unlink(sig_file_name);
 
-                       err = opkg_download(url, sig_file_name, NULL, NULL);
+                       err = opkg_download(url, sig_file_name, NULL, NULL, 0);
                        if (err) {
                                opkg_msg(ERROR, "Couldn't retrieve %s\n", url);
                        } else {
                                int err;
                                err = opkg_verify_file(list_file_name,
-                                                    sig_file_name);
+                                                      sig_file_name);
                                if (err == 0) {
                                        opkg_msg(INFO, "Signature check "
-                                                       "passed for %s",
-                                                       list_file_name);
+                                                "passed for %s",
+                                                list_file_name);
                                } else {
                                        opkg_msg(ERROR, "Signature check "
-                                                       "failed for %s",
-                                                       list_file_name);
+                                                "failed for %s",
+                                                list_file_name);
                                }
                        }
                        free(sig_file_name);
-                       free(list_file_name);
                        free(url);
                }
 #else
                opkg_msg(INFO, "Signature check skipped for %s as GPG support"
-                               " has not been enabled in this build\n",
-                               list_file_name);
+                        " has not been enabled in this build\n",
+                        list_file_name);
 #endif
+               free(list_file_name);
 
                sources_done++;
                progress(pdata, 100 * sources_done / sources_list_count);
@@ -701,8 +653,7 @@ opkg_update_package_lists(opkg_progress_callback_t progress_callback,
        return result;
 }
 
-static int
-pkg_compare_names_and_version(const void *a0, const void *b0)
+static int pkg_compare_names_and_version(const void *a0, const void *b0)
 {
        const pkg_t *a = *(const pkg_t **)a0;
        const pkg_t *b = *(const pkg_t **)b0;
@@ -716,8 +667,7 @@ pkg_compare_names_and_version(const void *a0, const void *b0)
        return ret;
 }
 
-int
-opkg_list_packages(opkg_package_callback_t callback, void *user_data)
+int opkg_list_packages(opkg_package_callback_t callback, void *user_data)
 {
        pkg_vec_t *all;
        int i;
@@ -756,9 +706,11 @@ opkg_list_upgradable_packages(opkg_package_callback_t callback, void *user_data)
 
        head = prepare_upgrade_list();
        for (node = active_list_next(head, head); node;
-            active_list_next(head, node)) {
-               old = list_entry(node, pkg_t, list);
-               new = pkg_hash_fetch_best_installation_candidate_by_name(old->name);
+            node = active_list_next(head, node)) {
+               old = node->pkg;
+               new =
+                   pkg_hash_fetch_best_installation_candidate_by_name(old->
+                                                                      name);
                if (new == NULL)
                        continue;
                callback(new, user_data);
@@ -767,10 +719,10 @@ opkg_list_upgradable_packages(opkg_package_callback_t callback, void *user_data)
        return 0;
 }
 
-pkg_t *
-opkg_find_package(const char *name, const char *ver, const char *arch,
-               const char *repo)
+pkg_t *opkg_find_package(const char *name, const char *ver, const char *arch,
+                        const char *repo)
 {
+       int pkg_found = 0;
        pkg_t *pkg = NULL;
        pkg_vec_t *all;
        int i;
@@ -797,7 +749,7 @@ 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_architecture(pkg), arch))
                                continue;
                }
 
@@ -808,20 +760,20 @@ opkg_find_package(const char *name, const char *ver, const char *arch,
                }
 
                /* match found */
+               pkg_found = 1;
                break;
        }
 
        pkg_vec_free(all);
 
-       return pkg;
+       return pkg_found ? pkg : NULL;
 }
 
 /**
  * @brief Check the accessibility of repositories.
- * @return return how many repositories cannot access. 0 means all okay. 
+ * @return return how many repositories cannot access. 0 means all okay.
  */
-int
-opkg_repository_accessibility_check(void)
+int opkg_repository_accessibility_check(void)
 {
        pkg_src_list_elt_t *iter;
        str_list_elt_t *iter1;
@@ -835,11 +787,12 @@ opkg_repository_accessibility_check(void)
        src = str_list_alloc();
 
        list_for_each_entry(iter, &conf->pkg_src_list.head, node) {
-               host = strstr(((pkg_src_t *)iter->data)->value, "://") + 3;
+               host = strstr(((pkg_src_t *) iter->data)->value, "://") + 3;
                end = index(host, '/');
                if (strstr(((pkg_src_t *) iter->data)->value, "://") && end)
                        stmp = xstrndup(((pkg_src_t *) iter->data)->value,
-                                    end - ((pkg_src_t *) iter->data)->value);
+                                       end -
+                                       ((pkg_src_t *) iter->data)->value);
                else
                        stmp = xstrdup(((pkg_src_t *) iter->data)->value);
 
@@ -863,7 +816,7 @@ opkg_repository_accessibility_check(void)
                iter1 = str_list_pop(src);
                repositories--;
 
-               if (opkg_download(iter1->data, "/dev/null", NULL, NULL))
+               if (opkg_download(iter1->data, "/dev/null", NULL, NULL, 0))
                        ret++;
                str_list_elt_deinit(iter1);
        }