opkg: fix gpg enabled builds and fix one compiler warning
[oweals/opkg-lede.git] / opkg_download.c
index e8bfce075946fcfd3de4ddca04caab5ab43aaa1f..bbd6efef868bf9deab58b6a58e703df96bd807d2 100644 (file)
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 */
-
+#include "config.h"
 #include <curl/curl.h>
+#ifdef HAVE_GPGME
+#include <gpgme.h>
+#endif
 
 #include "opkg.h"
 #include "opkg_download.h"
 #include "opkg_message.h"
+#include "opkg_state.h"
 
 #include "sprintf_alloc.h"
 #include "xsystem.h"
@@ -34,23 +38,37 @@ opkg_download_progress_callback opkg_cb_download_progress = NULL;
 #endif
 
 int
-curl_progress_func (void* data,
-                         double t, /* dltotal */
-                         double d, /* dlnow */
-                         double ultotal,
-                         double ulnow)
+curl_progress_func (char* url,
+                   double t, /* dltotal */
+                   double d, /* dlnow */
+                   double ultotal,
+                   double ulnow)
 {
     int i;
-    int p = d*100/t;
+    int p = (t) ? d*100/t : 0;
 
-#ifdef LIBOPKG
+#ifdef OPKG_LIB
     if (opkg_cb_download_progress)
     {
-       opkg_cb_download_progress (p);
+       static int prev = -1;
+
+       /* don't report the same percentage multiple times
+        * (this can occur due to rounding) */
+       if (prev == p)
+           return 0;
+       prev = p;
+
+       opkg_cb_download_progress (p, url);
        return 0;
     }
 #endif
 
+    /* skip progress bar if we haven't done started yet
+     * this prevents drawing the progress bar if we receive an error such as
+     * file not found */
+    if (t == 0)
+       return 0;
+
     printf ("\r%3d%% |", p);
     for (i = 1; i < 73; i++)
     {
@@ -71,7 +89,6 @@ int opkg_download(opkg_conf_t *conf, const char *src, const char *dest_file_name
     char *src_basec = strdup(src);
     char *src_base = basename(src_basec);
     char *tmp_file_location;
-    char *cmd;
 
     opkg_message(conf,OPKG_NOTICE,"Downloading %s\n", src);
        
@@ -142,8 +159,10 @@ int opkg_download(opkg_conf_t *conf, const char *src, const char *dest_file_name
     {
        curl_easy_setopt (curl, CURLOPT_URL, src);
        curl_easy_setopt (curl, CURLOPT_WRITEDATA, file);
-       curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
+       curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0);
+       curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, src);
        curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, curl_progress_func);
+       curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1);
        if (conf->http_proxy || conf->ftp_proxy)
        {
            char *userpwd;
@@ -155,6 +174,13 @@ int opkg_download(opkg_conf_t *conf, const char *src, const char *dest_file_name
        res = curl_easy_perform (curl);
        curl_easy_cleanup (curl);
        fclose (file);
+       if (res)
+       {
+           long error_code;
+           curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &error_code);
+           opkg_message(conf, OPKG_ERROR, "Failed to download %s, error %d\n", src, error_code);
+           return res;
+       }
 
     }
     else
@@ -178,6 +204,7 @@ int opkg_download_pkg(opkg_conf_t *conf, pkg_t *pkg, const char *dir)
 {
     int err;
     char *url;
+    char *pkgid;
 
     if (pkg->src == NULL) {
        opkg_message(conf,OPKG_ERROR, "ERROR: Package %s (parent %s) is not available from any configured src.\n",
@@ -185,6 +212,10 @@ int opkg_download_pkg(opkg_conf_t *conf, pkg_t *pkg, const char *dir)
        return -1;
     }
 
+    sprintf_alloc (&pkgid, "%s;%s;%s;", pkg->name, pkg->version, pkg->architecture);
+    opkg_set_current_state (OPKG_STATE_DOWNLOADING_PKG, pkgid);
+    free (pkgid);
+
     sprintf_alloc(&url, "%s/%s", pkg->src->value, pkg->filename);
 
     /* XXX: BUG: The pkg->filename might be something like
@@ -196,6 +227,7 @@ int opkg_download_pkg(opkg_conf_t *conf, pkg_t *pkg, const char *dir)
     err = opkg_download(conf, url, pkg->local_filename);
     free(url);
 
+    opkg_set_current_state (OPKG_STATE_NONE, NULL);
     return err;
 }
 
@@ -236,7 +268,7 @@ int opkg_prepare_url_for_install(opkg_conf_t *conf, const char *url, char **name
          if (err)
               return err;
          pkg->local_filename = strdup(url);
-         opkg_message(conf, OPKG_DEBUG2, "Package %s provided by hand \(%s\).\n", pkg->name,pkg->local_filename);
+         opkg_message(conf, OPKG_DEBUG2, "Package %s provided by hand (%s).\n", pkg->name,pkg->local_filename);
           pkg->provided_by_hand = 1;
 
      } else {
@@ -263,3 +295,52 @@ int opkg_prepare_url_for_install(opkg_conf_t *conf, const char *url, char **name
      }
      return 0;
 }
+
+int
+opkg_verify_file (char *text_file, char *sig_file)
+{
+#ifdef HAVE_GPGME
+    int status = -1;
+    gpgme_ctx_t ctx;
+    gpgme_data_t sig, text;
+    gpgme_error_t err = -1;
+    gpgme_verify_result_t result;
+    gpgme_signature_t s;
+    
+    err = gpgme_new (&ctx);
+
+    if (err)
+       return -1;
+
+    err = gpgme_data_new_from_file (&sig, sig_file, 1); 
+    if (err)
+       return -1;
+
+    err = gpgme_data_new_from_file (&text, text_file, 1); 
+    if (err)
+       return -1;
+
+    err = gpgme_op_verify (ctx, sig, text, NULL);
+
+    result = gpgme_op_verify_result (ctx);
+
+    /* see if any of the signitures matched */
+    s = result->signatures;
+    while (s)
+    {
+       status = gpg_err_code (s->status);
+       if (status == GPG_ERR_NO_ERROR)
+           break;
+       s = s->next;
+    }
+
+    gpgme_data_release (sig);
+    gpgme_data_release (text);
+    gpgme_release (ctx);
+
+    return status;
+#else
+    printf ("Signature check skipped because GPG support was not enabled in this build\n");
+    return 0;
+#endif
+}