libopkg: drop support for Release files
[oweals/opkg-lede.git] / libopkg / pkg_hash.c
index 06a0ac5881e89a747ace685f63b18a82a78d6bce..c6d7158032cb8a860171cebc796e44f566e1c672 100644 (file)
@@ -1,7 +1,7 @@
 /* opkg_hash.c - the opkg package management system
 
    Steven M. Ayer
-   
+
    Copyright (C) 2002 Compaq Computer Corporation
 
    This program is free software; you can redistribute it and/or
    General Public License for more details.
 */
 
-#include "includes.h"
-#include <errno.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
+#include <stdio.h>
 
 #include "hash_table.h"
 #include "pkg.h"
 #include "opkg_message.h"
 #include "pkg_vec.h"
 #include "pkg_hash.h"
+#include "parse_util.h"
 #include "pkg_parse.h"
 #include "opkg_utils.h"
+#include "sprintf_alloc.h"
+#include "file_util.h"
 #include "libbb/libbb.h"
+#include "libbb/gzip.h"
 
 void
 pkg_hash_init(void)
@@ -46,7 +46,7 @@ free_pkgs(const char *key, void *entry, void *data)
        /* Each entry in the hash table is an abstract package, which contains
         * a list of packages that provide the abstract package.
         */
-  
+
        ab_pkg = (abstract_pkg_t*) entry;
 
        if (ab_pkg->pkgs) {
@@ -71,6 +71,32 @@ pkg_hash_deinit(void)
        hash_table_deinit(&conf->pkg_hash);
 }
 
+int
+dist_hash_add_from_file(const char *lists_dir, pkg_src_t *dist)
+{
+       nv_pair_list_elt_t *l;
+       char *list_file, *subname;
+
+       list_for_each_entry(l , &conf->arch_list.head, node) {
+               nv_pair_t *nv = (nv_pair_t *)l->data;
+               sprintf_alloc(&subname, "%s-%s", dist->name, nv->name);
+               sprintf_alloc(&list_file, "%s/%s", lists_dir, subname);
+
+               if (file_exists(list_file)) {
+                       if (pkg_hash_add_from_file(list_file, dist, NULL, 0)) {
+                               free(list_file);
+                               return -1;
+                       }
+                       pkg_src_list_append (&conf->pkg_src_list, subname, dist->value, "__dummy__", 0);
+               }
+
+               free(list_file);
+       }
+
+       return 0;
+}
+
+
 int
 pkg_hash_add_from_file(const char *file_name,
                        pkg_src_t *src, pkg_dest_t *dest, int is_status_file)
@@ -80,8 +106,15 @@ pkg_hash_add_from_file(const char *file_name,
        char *buf;
        const size_t len = 4096;
        int ret = 0;
+       struct gzip_handle zh;
+
+       if (src && src->gzip) {
+               fp = gzip_fdopen(&zh, file_name);
+       }
+       else {
+               fp = fopen(file_name, "r");
+       }
 
-       fp = fopen(file_name, "r");
        if (fp == NULL) {
                opkg_perror(ERROR, "Failed to open %s", file_name);
                return -1;
@@ -94,8 +127,14 @@ pkg_hash_add_from_file(const char *file_name,
                pkg->src = src;
                pkg->dest = dest;
 
-               ret = pkg_parse_from_stream_nomalloc(pkg, fp, 0,
+               ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, 0,
                                &buf, len);
+
+               if (pkg->name == NULL) {
+                       /* probably just a blank line */
+                       ret = 1;
+               }
+
                if (ret) {
                        pkg_deinit (pkg);
                        free(pkg);
@@ -107,10 +146,10 @@ pkg_hash_add_from_file(const char *file_name,
                        continue;
                }
 
-               if (!pkg->architecture) {
+               if (!pkg->architecture || !pkg->arch_priority) {
                        char *version_str = pkg_version_str_alloc(pkg);
-                       opkg_msg(ERROR, "Package %s version %s has no "
-                                       "architecture specified, ignoring.\n",
+                       opkg_msg(NOTICE, "Package %s version %s has no "
+                                       "valid architecture, ignoring.\n",
                                        pkg->name, version_str);
                        free(version_str);
                        continue;
@@ -123,9 +162,71 @@ pkg_hash_add_from_file(const char *file_name,
        free(buf);
        fclose(fp);
 
+       if (src && src->gzip)
+               gzip_close(&zh);
+
        return ret;
 }
 
+/*
+ * Load in feed files from the cached "src" and/or "src/gz" locations.
+ */
+int
+pkg_hash_load_feeds(void)
+{
+       pkg_src_list_elt_t *iter;
+       pkg_src_t *src, *subdist;
+       char *list_file, *lists_dir;
+
+       opkg_msg(INFO, "\n");
+
+       lists_dir = conf->restrict_to_default_dest ?
+               conf->default_dest->lists_dir : conf->lists_dir;
+
+       for (iter = void_list_first(&conf->pkg_src_list); iter;
+                       iter = void_list_next(&conf->pkg_src_list, iter)) {
+
+               src = (pkg_src_t *)iter->data;
+
+               sprintf_alloc(&list_file, "%s/%s", lists_dir, src->name);
+
+               if (file_exists(list_file)) {
+                       if (pkg_hash_add_from_file(list_file, src, NULL, 0)) {
+                               free(list_file);
+                               return -1;
+                       }
+               }
+               free(list_file);
+       }
+
+       return 0;
+}
+
+/*
+ * Load in status files from the configured "dest"s.
+ */
+int
+pkg_hash_load_status_files(void)
+{
+       pkg_dest_list_elt_t *iter;
+       pkg_dest_t *dest;
+
+       opkg_msg(INFO, "\n");
+
+       for (iter = void_list_first(&conf->pkg_dest_list); iter;
+                       iter = void_list_next(&conf->pkg_dest_list, iter)) {
+
+               dest = (pkg_dest_t *)iter->data;
+
+               if (file_exists(dest->status_file_name)) {
+                       if (pkg_hash_add_from_file(dest->status_file_name, NULL, dest, 1))
+                               return -1;
+               }
+       }
+
+       return 0;
+}
+
 static abstract_pkg_t *
 abstract_pkg_fetch_by_name(const char * pkg_name)
 {
@@ -137,7 +238,7 @@ pkg_hash_fetch_best_installation_candidate(abstract_pkg_t *apkg,
                int (*constraint_fcn)(pkg_t *pkg, void *cdata),
                void *cdata, int quiet)
 {
-     int i;
+     int i, j;
      int nprovides = 0;
      int nmatching = 0;
      int wrong_arch_found = 0;
@@ -190,7 +291,7 @@ pkg_hash_fetch_best_installation_candidate(abstract_pkg_t *apkg,
          }
 
          if (replacement_apkg)
-              opkg_msg(DEBUG, "replacement_apkg=%s for provider_apkg=%s.\n", 
+              opkg_msg(DEBUG, "replacement_apkg=%s for provider_apkg=%s.\n",
                            replacement_apkg->name, provider_apkg->name);
 
          if (replacement_apkg && (replacement_apkg != provider_apkg)) {
@@ -205,19 +306,19 @@ pkg_hash_fetch_best_installation_candidate(abstract_pkg_t *apkg,
                               provider_apkg->name);
               continue;
          }
-    
+
 
          /* now check for supported architecture */
          {
               int max_count = 0;
 
               /* count packages matching max arch priority and keep track of last one */
-              for (i = 0; i < vec->len; i++) {
-                   pkg_t *maybe = vec->pkgs[i];
+              for (j=0; j<vec->len; j++) {
+                   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);
-                    /* We make sure not to add the same package twice. Need to search for the reason why 
+                    /* 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) && (! pkg_vec_contains(matching_pkgs, maybe))) {
                         max_count++;
@@ -256,7 +357,7 @@ pkg_hash_fetch_best_installation_candidate(abstract_pkg_t *apkg,
              good_pkg_by_name = matching;
             /* It has been provided by hand, so it is what user want */
              if (matching->provided_by_hand == 1)
-                break;                                 
+                break;
           }
      }
 
@@ -287,7 +388,7 @@ pkg_hash_fetch_best_installation_candidate(abstract_pkg_t *apkg,
                                matching->name, prio);
                   }
               }
-          
+
           }
 
      if (conf->verbosity >= INFO && matching_apkgs->len > 1) {
@@ -307,7 +408,7 @@ pkg_hash_fetch_best_installation_candidate(abstract_pkg_t *apkg,
      abstract_pkg_vec_free(matching_apkgs);
      abstract_pkg_vec_free(providers);
 
-     if (good_pkg_by_name) {   /* We found a good candidate, we will install it */ 
+     if (good_pkg_by_name) {   /* We found a good candidate, we will install it */
          return good_pkg_by_name;
      }
      if (held_pkg) {
@@ -347,7 +448,7 @@ pkg_name_constraint_fcn(pkg_t *pkg, void *cdata)
        if (strcmp(pkg->name, name) == 0)
                return 1;
        else
-               return 0;   
+               return 0;
 }
 
 static pkg_vec_t *
@@ -392,10 +493,10 @@ pkg_hash_fetch_by_name_version(const char *pkg_name, const char * version)
        pkg_vec_t * vec;
        int i;
        char *version_str = NULL;
-    
+
        if(!(vec = pkg_vec_fetch_by_name(pkg_name)))
                return NULL;
-    
+
        for(i = 0; i < vec->len; i++) {
                version_str = pkg_version_str_alloc(vec->pkgs[i]);
                if(!strcmp(version_str, version)) {
@@ -407,7 +508,7 @@ pkg_hash_fetch_by_name_version(const char *pkg_name, const char * version)
 
        if(i == vec->len)
                return NULL;
-    
+
        return vec->pkgs[i];
 }
 
@@ -562,30 +663,47 @@ hash_insert_pkg(pkg_t *pkg, int set_status)
        pkg->parent = ab_pkg;
 }
 
+static const char *
+strip_offline_root(const char *file_name)
+{
+       unsigned int len;
+
+       if (conf->offline_root) {
+               len = strlen(conf->offline_root);
+               if (strncmp(file_name, conf->offline_root, len) == 0)
+                       file_name += len;
+       }
+
+       return file_name;
+}
+
+void
+file_hash_remove(const char *file_name)
+{
+       file_name = strip_offline_root(file_name);
+       hash_table_remove(&conf->file_hash, file_name);
+}
 
 pkg_t *
 file_hash_get_file_owner(const char *file_name)
 {
-       return hash_table_get(&conf->file_hash, file_name); 
+       file_name = strip_offline_root(file_name);
+       return hash_table_get(&conf->file_hash, file_name);
 }
 
 void
 file_hash_set_file_owner(const char *file_name, pkg_t *owning_pkg)
 {
-       pkg_t *old_owning_pkg = hash_table_get(&conf->file_hash, file_name);
+       pkg_t *old_owning_pkg;
        int file_name_len = strlen(file_name);
 
        if (file_name[file_name_len -1] == '/')
                return;
 
-       if (conf->offline_root) {
-               unsigned int len = strlen(conf->offline_root);
-               if (strncmp(file_name, conf->offline_root, len) == 0) {
-                       file_name += len;
-               }
-       }
+       file_name = strip_offline_root(file_name);
 
-       hash_table_insert(&conf->file_hash, file_name, owning_pkg); 
+       old_owning_pkg = hash_table_get(&conf->file_hash, file_name);
+       hash_table_insert(&conf->file_hash, file_name, owning_pkg);
 
        if (old_owning_pkg) {
                pkg_get_installed_files(old_owning_pkg);