opkg: Fix -Wformat-overflow warning
[project/opkg-lede.git] / libopkg / opkg_install.c
index 76b658d342ae3163511a8aa7f7cb591001e7c13a..27c9484cfb8189e42cbc073eaa14a67c71c3507a 100644 (file)
@@ -15,8 +15,6 @@
    General Public License for more details.
 */
 
-#include "config.h"
-
 #include <stdio.h>
 #include <time.h>
 #include <signal.h>
@@ -47,7 +45,7 @@ static int satisfy_dependencies_for(pkg_t * pkg)
        int i, err;
        pkg_vec_t *depends = pkg_vec_alloc();
        pkg_t *dep;
-       char **tmp, **unresolved = NULL;
+       char **tmp, **unresolved = NULL, *prev = NULL;
        int ndepends;
 
        ndepends = pkg_hash_fetch_unsatisfied_dependencies(pkg, depends,
@@ -59,12 +57,17 @@ static int satisfy_dependencies_for(pkg_t * pkg)
                         pkg->name);
                tmp = unresolved;
                while (*unresolved) {
-                       opkg_message(ERROR, "\t%s", *unresolved);
+                       if (!prev || strcmp(*unresolved, prev))
+                               opkg_message(ERROR, "\t%s\n", *unresolved);
+                       prev = *unresolved;
+                       unresolved++;
+               }
+               unresolved = tmp;
+               while (*unresolved) {
                        free(*unresolved);
                        unresolved++;
                }
                free(tmp);
-               opkg_message(ERROR, "\n");
                if (!conf->force_depends) {
                        opkg_msg(INFO,
                                 "This could mean that your package list is out of date or that the packages\n"
@@ -193,10 +196,13 @@ static int update_file_ownership(pkg_t * new_pkg, pkg_t * old_pkg)
 static int verify_pkg_installable(pkg_t * pkg)
 {
        unsigned long kbs_available, pkg_size_kbs;
+       unsigned long installed_size;
        char *root_dir = NULL;
        struct stat s;
 
-       if (conf->force_space || pkg->installed_size == 0)
+       installed_size = (unsigned long) pkg_get_int(pkg, PKG_INSTALLED_SIZE);
+
+       if (conf->force_space || installed_size == 0)
                return 0;
 
        if (pkg->dest) {
@@ -212,7 +218,7 @@ static int verify_pkg_installable(pkg_t * pkg)
 
        kbs_available = get_available_kbytes(root_dir);
 
-       pkg_size_kbs = (pkg->installed_size + 1023) / 1024;
+       pkg_size_kbs = (installed_size + 1023) / 1024;
 
        if (pkg_size_kbs >= kbs_available) {
                opkg_msg(ERROR, "Only have %ldkb available on filesystem %s, "
@@ -229,19 +235,22 @@ static int unpack_pkg_control_files(pkg_t * pkg)
        int err;
        char *conffiles_file_name;
        char *root_dir;
+       char *tmp_unpack_dir;
        FILE *conffiles_file;
+       conffile_list_t *cl;
 
-       sprintf_alloc(&pkg->tmp_unpack_dir, "%s/%s-XXXXXX", conf->tmp_dir,
+       sprintf_alloc(&tmp_unpack_dir, "%s/%s-XXXXXX", conf->tmp_dir,
                      pkg->name);
 
-       pkg->tmp_unpack_dir = mkdtemp(pkg->tmp_unpack_dir);
-       if (pkg->tmp_unpack_dir == NULL) {
-               opkg_perror(ERROR, "Failed to create temporary directory '%s'",
-                           pkg->tmp_unpack_dir);
+       tmp_unpack_dir = mkdtemp(tmp_unpack_dir);
+       if (tmp_unpack_dir == NULL) {
+               opkg_perror(ERROR, "Failed to create temporary directory");
                return -1;
        }
 
-       err = pkg_extract_control_files_to_dir(pkg, pkg->tmp_unpack_dir);
+       pkg_set_string(pkg, PKG_TMP_UNPACK_DIR, tmp_unpack_dir);
+
+       err = pkg_extract_control_files_to_dir(pkg, tmp_unpack_dir);
        if (err) {
                return err;
        }
@@ -252,12 +261,13 @@ static int unpack_pkg_control_files(pkg_t * pkg)
           move all of unpack_pkg_control_files to that function. */
 
        /* Don't need to re-read conffiles if we already have it */
-       if (!nv_pair_list_empty(&pkg->conffiles)) {
+       cl = pkg_get_ptr(pkg, PKG_CONFFILES);
+       if (cl && !nv_pair_list_empty(cl)) {
                return 0;
        }
 
        sprintf_alloc(&conffiles_file_name, "%s/conffiles",
-                     pkg->tmp_unpack_dir);
+                     tmp_unpack_dir);
        if (!file_exists(conffiles_file_name)) {
                free(conffiles_file_name);
                return 0;
@@ -271,6 +281,9 @@ static int unpack_pkg_control_files(pkg_t * pkg)
        }
        free(conffiles_file_name);
 
+       cl = xcalloc(1, sizeof(*cl));
+       conffile_list_init(cl);
+
        while (1) {
                char *cf_name;
                char *cf_name_in_dest;
@@ -301,12 +314,14 @@ static int unpack_pkg_control_files(pkg_t * pkg)
 
                /* Can't get an md5sum now, (file isn't extracted yet).
                   We'll wait until resolve_conffiles */
-               conffile_list_append(&pkg->conffiles, cf_name_in_dest, NULL);
+               conffile_list_append(cl, cf_name_in_dest, NULL);
 
                free(cf_name);
                free(cf_name_in_dest);
        }
 
+       pkg_set_ptr(pkg, PKG_CONFFILES, cl);
+
        fclose(conffiles_file);
 
        return 0;
@@ -318,28 +333,20 @@ static int unpack_pkg_control_files(pkg_t * pkg)
  */
 static int pkg_remove_orphan_dependent(pkg_t * pkg, pkg_t * old_pkg)
 {
-       int i, j, k, l, found, r, err = 0;
+       int j, l, found, r, err = 0;
        int n_deps;
        pkg_t *p;
        struct compound_depend *cd0, *cd1;
        abstract_pkg_t **dependents;
 
-       int count0 = old_pkg->pre_depends_count +
-           old_pkg->depends_count +
-           old_pkg->recommends_count + old_pkg->suggests_count;
-       int count1 = pkg->pre_depends_count +
-           pkg->depends_count + pkg->recommends_count + pkg->suggests_count;
-
-       for (i = 0; i < count0; i++) {
-               cd0 = &old_pkg->depends[i];
+       for (cd0 = pkg_get_ptr(old_pkg, PKG_DEPENDS); cd0 && cd0->type; cd0++) {
                if (cd0->type != DEPEND)
                        continue;
                for (j = 0; j < cd0->possibility_count; j++) {
 
                        found = 0;
 
-                       for (k = 0; k < count1; k++) {
-                               cd1 = &pkg->depends[k];
+                       for (cd1 = pkg_get_ptr(pkg, PKG_DEPENDS); cd1 && cd1->type; cd1++) {
                                if (cd1->type != DEPEND)
                                        continue;
                                for (l = 0; l < cd1->possibility_count; l++) {
@@ -399,11 +406,11 @@ static int pkg_remove_orphan_dependent(pkg_t * pkg, pkg_t * old_pkg)
 static int
 pkg_get_installed_replacees(pkg_t * pkg, pkg_vec_t * installed_replacees)
 {
-       abstract_pkg_t **replaces = pkg->replaces;
-       int replaces_count = pkg->replaces_count;
-       int i, j;
-       for (i = 0; i < replaces_count; i++) {
-               abstract_pkg_t *ab_pkg = replaces[i];
+       abstract_pkg_t **replaces = pkg_get_ptr(pkg, PKG_REPLACES);
+       int j;
+
+       while (replaces && *replaces) {
+               abstract_pkg_t *ab_pkg = *replaces++;
                pkg_vec_t *pkg_vec = ab_pkg->pkgs;
                if (pkg_vec) {
                        for (j = 0; j < pkg_vec->len; j++) {
@@ -417,6 +424,7 @@ pkg_get_installed_replacees(pkg_t * pkg, pkg_vec_t * installed_replacees)
                        }
                }
        }
+
        return installed_replacees->len;
 }
 
@@ -689,14 +697,17 @@ static int backup_modified_conffiles(pkg_t * pkg, pkg_t * old_pkg)
        int err;
        conffile_list_elt_t *iter;
        conffile_t *cf;
+       conffile_list_t *cl;
 
        if (conf->noaction)
                return 0;
 
        /* Backup all modified conffiles */
        if (old_pkg) {
-               for (iter = nv_pair_list_first(&old_pkg->conffiles); iter;
-                    iter = nv_pair_list_next(&old_pkg->conffiles, iter)) {
+               cl = pkg_get_ptr(old_pkg, PKG_CONFFILES);
+
+               for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
+                    iter = nv_pair_list_next(cl, iter)) {
                        char *cf_name;
 
                        cf = iter->data;
@@ -715,8 +726,10 @@ static int backup_modified_conffiles(pkg_t * pkg, pkg_t * old_pkg)
        }
 
        /* Backup all conffiles that were not conffiles in old_pkg */
-       for (iter = nv_pair_list_first(&pkg->conffiles); iter;
-            iter = nv_pair_list_next(&pkg->conffiles, iter)) {
+       cl = pkg_get_ptr(pkg, PKG_CONFFILES);
+
+       for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
+            iter = nv_pair_list_next(cl, iter)) {
                char *cf_name;
                cf = (conffile_t *) iter->data;
                cf_name = root_filename_alloc(cf->name);
@@ -739,17 +752,22 @@ static int backup_modified_conffiles(pkg_t * pkg, pkg_t * old_pkg)
 
 static int backup_modified_conffiles_unwind(pkg_t * pkg, pkg_t * old_pkg)
 {
+       conffile_list_t *cl;
        conffile_list_elt_t *iter;
 
        if (old_pkg) {
-               for (iter = nv_pair_list_first(&old_pkg->conffiles); iter;
-                    iter = nv_pair_list_next(&old_pkg->conffiles, iter)) {
+               cl = pkg_get_ptr(old_pkg, PKG_CONFFILES);
+
+               for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
+                    iter = nv_pair_list_next(cl, iter)) {
                        backup_remove(((nv_pair_t *) iter->data)->name);
                }
        }
 
-       for (iter = nv_pair_list_first(&pkg->conffiles); iter;
-            iter = nv_pair_list_next(&pkg->conffiles, iter)) {
+       cl = pkg_get_ptr(pkg, PKG_CONFFILES);
+
+       for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
+            iter = nv_pair_list_next(cl, iter)) {
                backup_remove(((nv_pair_t *) iter->data)->name);
        }
 
@@ -870,8 +888,6 @@ static int check_data_file_clashes_change(pkg_t * pkg, pkg_t * old_pkg)
        str_list_t *files_list;
        str_list_elt_t *iter, *niter;
 
-       char *root_filename = NULL;
-
        files_list = pkg_get_installed_files(pkg);
        if (files_list == NULL)
                return -1;
@@ -880,12 +896,7 @@ static int check_data_file_clashes_change(pkg_t * pkg, pkg_t * old_pkg)
             str_list_next(files_list, iter); iter;
             iter = niter, niter = str_list_next(files_list, niter)) {
                char *filename = (char *)iter->data;
-               if (root_filename) {
-                       free(root_filename);
-                       root_filename = NULL;
-               }
-               root_filename = root_filename_alloc(filename);
-               if (file_exists(root_filename) && (!file_is_dir(root_filename))) {
+               if (file_exists(filename) && (!file_is_dir(filename))) {
                        pkg_t *owner;
 
                        owner = file_hash_get_file_owner(filename);
@@ -912,10 +923,6 @@ static int check_data_file_clashes_change(pkg_t * pkg, pkg_t * old_pkg)
 
                }
        }
-       if (root_filename) {
-               free(root_filename);
-               root_filename = NULL;
-       }
        pkg_free_installed_files(pkg);
 
        return 0;
@@ -1076,13 +1083,6 @@ static int install_data_files(pkg_t * pkg)
                return err;
        }
 
-       /* The "Essential" control field may only be present in the control
-        * file and not in the Packages list. Ensure we capture it regardless.
-        *
-        * XXX: This should be fixed outside of opkg, in the Package list.
-        */
-       set_flags_from_control(pkg);
-
        opkg_msg(DEBUG, "Calling pkg_write_filelist.\n");
        err = pkg_write_filelist(pkg);
        if (err)
@@ -1105,6 +1105,7 @@ static int install_data_files(pkg_t * pkg)
 static int resolve_conffiles(pkg_t * pkg)
 {
        conffile_list_elt_t *iter;
+       conffile_list_t *cl;
        conffile_t *cf;
        char *cf_backup;
        char *chksum;
@@ -1112,8 +1113,10 @@ static int resolve_conffiles(pkg_t * pkg)
        if (conf->noaction)
                return 0;
 
-       for (iter = nv_pair_list_first(&pkg->conffiles); iter;
-            iter = nv_pair_list_next(&pkg->conffiles, iter)) {
+       cl = pkg_get_ptr(pkg, PKG_CONFFILES);
+
+       for (iter = cl ? nv_pair_list_first(cl) : NULL; iter;
+            iter = nv_pair_list_next(cl, iter)) {
                char *root_filename;
                cf = (conffile_t *) iter->data;
                root_filename = root_filename_alloc(cf->name);
@@ -1132,15 +1135,12 @@ static int resolve_conffiles(pkg_t * pkg)
 
                if (file_exists(cf_backup)) {
                        /* Let's compute md5 to test if files are changed */
-#ifdef HAVE_MD5
                        if (cf->value && strlen(cf->value) > 33) {
                                chksum = file_sha256sum_alloc(cf_backup);
                        } else {
                                chksum = file_md5sum_alloc(cf_backup);
                        }
-#else
-                       chksum = file_sha256sum_alloc(cf_backup);
-#endif
+
                        if (chksum && cf->value
                            && strcmp(cf->value, chksum) != 0) {
                                if (conf->force_maintainer) {
@@ -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,13 @@ 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;
-#ifdef HAVE_SHA256
-       char *file_sha256;
-#endif
+       char *file_md5, *pkg_md5;
+       char *file_sha256, *pkg_sha256;
        sigset_t newset, oldset;
+       const char *local_filename;
+       long long int pkg_expected_size;
+       struct stat pkg_stat;
+       time_t now;
 
        if (from_upgrade)
                message = 1;    /* Coming from an upgrade, and should change the output message */
@@ -1264,7 +1266,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_architecture(pkg), pkg->name);
                return -1;
        }
        if (pkg->state_status == SS_INSTALLED && conf->nodeps == 0) {
@@ -1307,7 +1309,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)
@@ -1323,10 +1327,12 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
                                 pkg->name);
                        return -1;
                }
+
+               local_filename = pkg_get_string(pkg, PKG_LOCAL_FILENAME);
        }
 
        /* check that the repository is valid */
-#if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN)
+#if defined(HAVE_USIGN)
        char *list_file_name, *sig_file_name, *lists_dir;
 
        /* check to ensure the package has come from a repository */
@@ -1361,11 +1367,35 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
        }
 #endif
 
-#ifdef HAVE_MD5
+       /* Check file size */
+       err = lstat(local_filename, &pkg_stat);
+
+       if (err) {
+               opkg_msg(ERROR, "Failed to stat %s: %s\n",
+                        local_filename, strerror(errno));
+               return -1;
+       }
+
+       pkg_expected_size = pkg_get_int(pkg, PKG_SIZE);
+
+       if (pkg_expected_size > 0 && pkg_stat.st_size != pkg_expected_size) {
+               if (!conf->force_checksum) {
+                       opkg_msg(ERROR,
+                                "Package size mismatch: %s is %lld bytes, expecting %lld bytes\n",
+                                pkg->name, (long long int)pkg_stat.st_size, pkg_expected_size);
+                       return -1;
+               } else {
+                       opkg_msg(NOTICE,
+                                "Ignored %s size mismatch.\n",
+                                pkg->name);
+               }
+       }
+
        /* 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_md5(pkg);
+       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. "
@@ -1381,13 +1411,12 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
                if (file_md5)
                        free(file_md5);
        }
-#endif
 
-#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_sha256(pkg);
+       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. "
@@ -1404,7 +1433,7 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
                if (file_sha256)
                        free(file_sha256);
        }
-#endif
+
        if (conf->download_only) {
                if (conf->nodeps == 0) {
                        err = satisfy_dependencies_for(pkg);
@@ -1414,11 +1443,11 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
                return 0;
        }
 
-       if (pkg->tmp_unpack_dir == NULL) {
+       if (!pkg_get_string(pkg, PKG_TMP_UNPACK_DIR)) {
                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;
                }
        }
@@ -1546,7 +1575,8 @@ int opkg_install_pkg(pkg_t * pkg, int from_upgrade)
        if (old_pkg)
                old_pkg->state_status = SS_NOT_INSTALLED;
 
-       time(&pkg->installed_time);
+       now = time(NULL);
+       pkg_set_int(pkg, PKG_INSTALLED_TIME, now);
 
        ab_pkg = pkg->parent;
        if (ab_pkg)