+ char *tmp;
+ int err, result = 0;
+ char *lists_dir;
+ pkg_src_list_elt_t *iter;
+ pkg_src_t *src;
+ int sources_list_count, sources_done;
+ opkg_progress_data_t pdata;
+
+ pdata.action = OPKG_DOWNLOAD;
+ pdata.pkg = NULL;
+ progress(pdata, 0);
+
+ sprintf_alloc(&lists_dir, "%s", (conf->restrict_to_default_dest)
+ ? conf->default_dest->lists_dir : conf->lists_dir);
+
+ if (!file_is_dir(lists_dir)) {
+ if (file_exists(lists_dir)) {
+ opkg_msg(ERROR, "%s is not a directory\n", lists_dir);
+ free(lists_dir);
+ return 1;
+ }
+
+ err = file_mkdir_hier(lists_dir, 0755);
+ if (err) {
+ opkg_msg(ERROR, "Couldn't create lists_dir %s\n",
+ lists_dir);
+ free(lists_dir);
+ return 1;
+ }
+ }
+
+ sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir);
+ if (mkdtemp(tmp) == NULL) {
+ opkg_perror(ERROR, "Coundn't create temporary directory %s",
+ tmp);
+ free(lists_dir);
+ free(tmp);
+ return 1;
+ }
+
+ /* count the number of sources so we can give some progress updates */
+ sources_list_count = 0;
+ sources_done = 0;
+ list_for_each_entry(iter, &conf->pkg_src_list.head, node) {
+ sources_list_count++;
+ }
+
+ list_for_each_entry(iter, &conf->pkg_src_list.head, node) {
+ char *url, *list_file_name = NULL;
+
+ src = (pkg_src_t *) iter->data;
+
+ if (src->extra_data) /* debian style? */
+ sprintf_alloc(&url, "%s/%s/%s", src->value,
+ src->extra_data,
+ src->gzip ? "Packages.gz" : "Packages");
+ else
+ sprintf_alloc(&url, "%s/%s", src->value,
+ src->gzip ? "Packages.gz" : "Packages");
+
+ sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
+
+ if (opkg_download(url, list_file_name, 0)) {
+ opkg_msg(ERROR, "Couldn't retrieve %s\n", url);
+ result = -1;
+ }
+ free(url);
+
+#if defined(HAVE_USIGN)
+ if (conf->check_signature) {
+ char *sig_file_name;
+ /* download detached signitures to verify the package lists */
+ /* get the url for the sig file */
+ if (src->extra_data) /* debian style? */
+ sprintf_alloc(&url, "%s/%s/%s", src->value,
+ src->extra_data, "Packages.sig");
+ else
+ sprintf_alloc(&url, "%s/%s", src->value,
+ "Packages.sig");
+
+ /* create filename for signature */
+ sprintf_alloc(&sig_file_name, "%s/%s.sig", lists_dir,
+ src->name);
+
+ /* make sure there is no existing signature file */
+ unlink(sig_file_name);
+
+ err = opkg_download(url, sig_file_name, 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);
+ if (err == 0) {
+ opkg_msg(INFO, "Signature check "
+ "passed for %s",
+ list_file_name);
+ } else {
+ opkg_msg(ERROR, "Signature check "
+ "failed for %s",
+ list_file_name);
+ }
+ }
+ free(sig_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);
+#endif
+ free(list_file_name);
+
+ sources_done++;
+ progress(pdata, 100 * sources_done / sources_list_count);
+ }
+
+ rmdir(tmp);
+ free(tmp);
+ free(lists_dir);
+
+ /* Now re-read the package lists to update package hash tables. */
+ opkg_re_read_config_files();
+
+ return result;
+}
+
+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;
+ int ret;
+
+ ret = strcmp(a->name, b->name);
+
+ if (ret == 0)
+ ret = pkg_compare_versions(a, b);
+
+ return ret;
+}
+
+int opkg_list_packages(opkg_package_callback_t callback, void *user_data)
+{
+ pkg_vec_t *all;
+ int i;
+
+ opkg_assert(callback);
+
+ all = pkg_vec_alloc();
+ pkg_hash_fetch_available(all);
+
+ pkg_vec_sort(all, pkg_compare_names_and_version);
+
+ for (i = 0; i < all->len; i++) {
+ pkg_t *pkg;
+
+ pkg = all->pkgs[i];
+
+ callback(pkg, user_data);
+ }
+
+ pkg_vec_free(all);
+
+ return 0;