X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=inline;f=libopkg%2Fpkg.c;h=98a929cd4d0d788d00fdaabd3f3724d7c307defb;hb=f5afe41a675508672a51d90b84d61a124cd8939d;hp=93fd20aa9842bca54a88c3bea351c57b5c9d4e8c;hpb=d281eab6487605176bd20efcfe21dabbd1514735;p=oweals%2Fopkg-lede.git diff --git a/libopkg/pkg.c b/libopkg/pkg.c index 93fd20a..98a929c 100644 --- a/libopkg/pkg.c +++ b/libopkg/pkg.c @@ -1,4 +1,4 @@ -/* pkg.c - the itsy package management system +/* pkg.c - the opkg package management system Carl D. Worth @@ -15,9 +15,11 @@ General Public License for more details. */ -#include "opkg.h" +#include "includes.h" #include +#include #include +#include #include #include "pkg.h" @@ -76,7 +78,7 @@ pkg_t *pkg_new(void) { pkg_t *pkg; - pkg = malloc(sizeof(pkg_t)); + pkg = calloc(1, sizeof(pkg_t)); if (pkg == NULL) { fprintf(stderr, "%s: out of memory\n", __FUNCTION__); return NULL; @@ -89,12 +91,10 @@ pkg_t *pkg_new(void) int pkg_init(pkg_t *pkg) { - memset(pkg, 0, sizeof(pkg_t)); pkg->name = NULL; pkg->epoch = 0; pkg->version = NULL; pkg->revision = NULL; - pkg->familiar_revision = NULL; pkg->dest = NULL; pkg->src = NULL; pkg->architecture = NULL; @@ -112,6 +112,8 @@ int pkg_init(pkg_t *pkg) pkg->recommends_str = NULL; pkg->suggests_count = 0; pkg->recommends_count = 0; + + active_list_init(&pkg->list); /* Abhaya: added init for conflicts fields */ pkg->conflicts = NULL; @@ -142,17 +144,31 @@ int pkg_init(pkg_t *pkg) return 0; } +void compound_depend_deinit (compound_depend_t *depends) +{ + int i; + for (i = 0; i < depends->possibility_count; i++) + { + depend_t *d; + d = depends->possibilities[i]; + free (d->version); + free (d); + } + free (depends->possibilities); +} + void pkg_deinit(pkg_t *pkg) { + int i; + free(pkg->name); pkg->name = NULL; pkg->epoch = 0; free(pkg->version); pkg->version = NULL; - /* revision and familiar_revision share storage with version, so + /* revision shares storage with version, so don't free */ pkg->revision = NULL; - pkg->familiar_revision = NULL; /* owned by opkg_conf_t */ pkg->dest = NULL; /* owned by opkg_conf_t */ @@ -168,18 +184,66 @@ void pkg_deinit(pkg_t *pkg) pkg->state_want = SW_UNKNOWN; pkg->state_flag = SF_OK; pkg->state_status = SS_NOT_INSTALLED; + + active_list_clear(&pkg->list); + + free (pkg->replaces); + pkg->replaces = NULL; + + for (i = 0; i < pkg->depends_count; i++) + free (pkg->depends_str[i]); free(pkg->depends_str); pkg->depends_str = NULL; + + for (i = 0; i < pkg->provides_count; i++) + free (pkg->provides_str[i]); free(pkg->provides_str); pkg->provides_str = NULL; - pkg->depends_count = 0; - /* XXX: CLEANUP: MEMORY_LEAK: how to free up pkg->depends ? */ + + for (i = 0; i < pkg->conflicts_count; i++) + free (pkg->conflicts_str[i]); + free(pkg->conflicts_str); + pkg->conflicts_str = NULL; + + for (i = 0; i < pkg->replaces_count; i++) + free (pkg->replaces_str[i]); + free(pkg->replaces_str); + pkg->replaces_str = NULL; + + for (i = 0; i < pkg->recommends_count; i++) + free (pkg->recommends_str[i]); + free(pkg->recommends_str); + pkg->recommends_str = NULL; + + for (i = 0; i < pkg->suggests_count; i++) + free (pkg->suggests_str[i]); + free(pkg->suggests_str); + pkg->suggests_str = NULL; + + if (pkg->depends) + { + int count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count; + int x; + + for (x = 0; x < count; x++) + compound_depend_deinit (&pkg->depends[x]); + free (pkg->depends); + } + + if (pkg->conflicts) + { + int x; + for (x = 0; x < pkg->conflicts_count; x++) + compound_depend_deinit (&pkg->conflicts[x]); + free (pkg->conflicts); + } + + free (pkg->provides); + pkg->pre_depends_count = 0; free(pkg->pre_depends_str); pkg->pre_depends_str = NULL; pkg->provides_count = 0; - /* XXX: CLEANUP: MEMORY_LEAK: how to free up pkg->provides ? */ - /* XXX: CLEANUP: MEMORY_LEAK: how to free up pkg->suggests ? */ free(pkg->filename); pkg->filename = NULL; free(pkg->local_filename); @@ -206,6 +270,8 @@ void pkg_deinit(pkg_t *pkg) pkg->installed_files_ref_cnt = 1; pkg_free_installed_files(pkg); pkg->essential = 0; + free (pkg->tags); + pkg->tags = NULL; } int pkg_init_from_file(pkg_t *pkg, const char *filename) @@ -347,8 +413,8 @@ int pkg_merge(pkg_t *oldpkg, pkg_t *newpkg, int set_status) oldpkg->priority = str_dup_safe(newpkg->priority); if (!oldpkg->source) oldpkg->source = str_dup_safe(newpkg->source); - if (oldpkg->conffiles.head == NULL){ - oldpkg->conffiles = newpkg->conffiles; + if (nv_pair_list_empty(&oldpkg->conffiles)){ + list_splice_init(&newpkg->conffiles.head, &oldpkg->conffiles.head); conffile_list_init(&newpkg->conffiles); } if (!oldpkg->installed_files){ @@ -366,7 +432,7 @@ abstract_pkg_t *abstract_pkg_new(void) { abstract_pkg_t * ab_pkg; - ab_pkg = malloc(sizeof(abstract_pkg_t)); + ab_pkg = calloc(1, sizeof(abstract_pkg_t)); if (ab_pkg == NULL) { fprintf(stderr, "%s: out of memory\n", __FUNCTION__); @@ -381,8 +447,6 @@ abstract_pkg_t *abstract_pkg_new(void) int abstract_pkg_init(abstract_pkg_t *ab_pkg) { - memset(ab_pkg, 0, sizeof(abstract_pkg_t)); - ab_pkg->provided_by = abstract_pkg_vec_alloc(); if (ab_pkg->provided_by==NULL){ return -1; @@ -398,7 +462,10 @@ void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){ char **raw =NULL; char **raw_start=NULL; - temp_str = (char *) malloc (strlen(pkg->dest->info_dir)+strlen(pkg->name)+12); + size_t str_size = strlen(pkg->dest->info_dir)+strlen(pkg->name)+12; + temp_str = (char *) alloca (str_size); + memset(temp_str, 0 , str_size); + if (temp_str == NULL ){ opkg_message(conf, OPKG_INFO, "Out of memory in %s\n", __FUNCTION__); return; @@ -423,102 +490,132 @@ void set_flags_from_control(opkg_conf_t *conf, pkg_t *pkg){ } free(raw_start); - free(temp_str); return ; } +#define CHECK_BUFF_SIZE(buff, line, buf_size, page_size) do { \ + if (strlen(buff) + strlen(line) >= (buf_size)) { \ + buf_size += page_size; \ + buff = realloc(buff, buf_size); \ + } \ + } while(0) char * pkg_formatted_info(pkg_t *pkg ) { char *line; char * buff; + const size_t page_size = 8192; + size_t buff_size = page_size; - buff = malloc(8192); + buff = calloc(1, buff_size); if (buff == NULL) { fprintf(stderr, "%s: out of memory\n", __FUNCTION__); return NULL; } - buff[0] = '\0'; - line = pkg_formatted_field(pkg, "Package"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Version"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Depends"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Recommends"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Suggests"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Provides"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Replaces"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Conflicts"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Status"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Section"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Essential"); /* @@@@ should be removed in future release. *//* I do not agree with this Pigi*/ + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Architecture"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Maintainer"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "MD5sum"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Size"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Filename"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Conffiles"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Source"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Description"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); line = pkg_formatted_field(pkg, "Installed-Time"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); + strncat(buff ,line, strlen(line)); + free(line); + + line = pkg_formatted_field(pkg, "Tags"); + CHECK_BUFF_SIZE(buff, line, buff_size, page_size); strncat(buff ,line, strlen(line)); free(line); @@ -576,14 +673,14 @@ char * pkg_formatted_field(pkg_t *pkg, const char *field ) conffile_list_elt_t *iter; char confstr[LINE_LEN]; - if (pkg->conffiles.head == NULL) { + if (nv_pair_list_empty(&pkg->conffiles)) { return temp; } len = 14 ; - for (iter = pkg->conffiles.head; iter; iter = iter->next) { - if (iter->data->name && iter->data->value) { - len = len + (strlen(iter->data->name)+strlen(iter->data->value)+5); + for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) { + if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) { + len = len + (strlen(((conffile_t *)iter->data)->name)+strlen(((conffile_t *)iter->data)->value)+5); } } temp = (char *)realloc(temp,len); @@ -593,9 +690,11 @@ char * pkg_formatted_field(pkg_t *pkg, const char *field ) } temp[0]='\0'; strncpy(temp, "Conffiles:\n", 12); - for (iter = pkg->conffiles.head; iter; iter = iter->next) { - if (iter->data->name && iter->data->value) { - snprintf(confstr, LINE_LEN, "%s %s\n", iter->data->name, iter->data->value); + for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) { + if (((conffile_t *)iter->data)->name && ((conffile_t *)iter->data)->value) { + snprintf(confstr, LINE_LEN, "%s %s\n", + ((conffile_t *)iter->data)->name, + ((conffile_t *)iter->data)->value); strncat(temp, confstr, strlen(confstr)); } } @@ -937,6 +1036,21 @@ char * pkg_formatted_field(pkg_t *pkg, const char *field ) } } break; + case 't': + case 'T': + if (strcasecmp(field, "Tags") == 0) { + /* Tags */ + if (pkg->tags) { + temp = (char *)realloc(temp,strlen(pkg->tags)+8); + if ( temp == NULL ){ + fprintf(stderr, "%s: out of memory\n", __FUNCTION__); + return NULL; + } + temp[0]='\0'; + snprintf(temp, (strlen(pkg->tags)+8), "Tags: %s\n", pkg->tags); + } + } + break; case 'v': case 'V': { /* Version */ @@ -971,6 +1085,7 @@ char * pkg_formatted_field(pkg_t *pkg, const char *field ) void pkg_print_info(pkg_t *pkg, FILE *file) { + int t=0; char * buff; if (pkg == NULL) { return; @@ -980,7 +1095,7 @@ void pkg_print_info(pkg_t *pkg, FILE *file) if ( buff == NULL ) return; if (strlen(buff)>2){ - fwrite(buff, 1, strlen(buff), file); + t = fwrite(buff, 1, strlen(buff), file); //#~rzr:TODO } free(buff); } @@ -998,7 +1113,7 @@ void pkg_print_status(pkg_t * pkg, FILE * file) can be found in th available file. But, someone proposed the idea to make it possible to - reconstruct a .ipk from an installed package, (ie. for beaming + reconstruct a .opk from an installed package, (ie. for beaming from one handheld to another). So, maybe we actually want a few more fields here, (depends, suggests, etc.), so that that would be guaranteed to work even in the absence of more information @@ -1138,10 +1253,10 @@ int pkg_version_satisfied(pkg_t *it, pkg_t *ref, const char *op) return 0; } -int pkg_name_version_and_architecture_compare(void *p1, void *p2) +int pkg_name_version_and_architecture_compare(const void *p1, const void *p2) { - const pkg_t *a = *(const pkg_t **)p1; - const pkg_t *b = *(const pkg_t **)p2; + const pkg_t *a = *(const pkg_t**) p1; + const pkg_t *b = *(const pkg_t**) p2; int namecmp; int vercmp; if (!a->name || !b->name) { @@ -1168,7 +1283,7 @@ int pkg_name_version_and_architecture_compare(void *p1, void *p2) return 0; } -int abstract_pkg_name_compare(void *p1, void *p2) +int abstract_pkg_name_compare(const void *p1, const void *p2) { const abstract_pkg_t *a = *(const abstract_pkg_t **)p1; const abstract_pkg_t *b = *(const abstract_pkg_t **)p2; @@ -1230,7 +1345,7 @@ str_list_t *pkg_get_installed_files(pkg_t *pkg) return NULL; } - /* For uninstalled packages, get the file list firectly from the package. + /* For uninstalled packages, get the file list directly from the package. For installed packages, look at the package.list file in the database. */ if (pkg->state_status == SS_NOT_INSTALLED || pkg->dest == NULL) { @@ -1312,22 +1427,13 @@ str_list_t *pkg_get_installed_files(pkg_t *pkg) work. */ int pkg_free_installed_files(pkg_t *pkg) { - str_list_elt_t *iter; - pkg->installed_files_ref_cnt--; - if (pkg->installed_files_ref_cnt > 0) { + + if (pkg->installed_files_ref_cnt > 0) return 0; - } if (pkg->installed_files) { - - for (iter = pkg->installed_files->head; iter; iter = iter->next) { - /* malloced in pkg_get_installed_files */ - free (iter->data); - iter->data = NULL; - } - - str_list_deinit(pkg->installed_files); + str_list_deinit(pkg->installed_files); } pkg->installed_files = NULL; @@ -1365,8 +1471,8 @@ conffile_t *pkg_get_conffile(pkg_t *pkg, const char *file_name) return NULL; } - for (iter = pkg->conffiles.head; iter; iter = iter->next) { - conffile = iter->data; + for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) { + conffile = (conffile_t *)iter->data; if (strcmp(conffile->name, file_name) == 0) { return conffile; @@ -1411,8 +1517,24 @@ int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg, scripts when running with offline_root mode and/or a dest other than '/'. I've been playing around with some clever chroot tricks and I might come up with something workable. */ + /* + * Attempt to provide a restricted environment for offline operation + * Need the following set as a minimum: + * OPKG_OFFLINE_ROOT = absolute path to root dir + * D = absolute path to root dir (for OE generated postinst) + * PATH = something safe (a restricted set of utilities) + */ + + bool AllowOfflineMode = false; if (conf->offline_root) { setenv("OPKG_OFFLINE_ROOT", conf->offline_root, 1); + setenv("D", conf->offline_root, 1); + if (NULL == conf->offline_root_path || '\0' == conf->offline_root_path[0]) { + setenv("PATH", "/dev/null", 1); + } else { + setenv("PATH", conf->offline_root_path, 1); + AllowOfflineMode = true; + } } setenv("PKG_ROOT", @@ -1423,7 +1545,7 @@ int pkg_run_script(opkg_conf_t *conf, pkg_t *pkg, return 0; } - if (conf->offline_root) { + if (conf->offline_root && !AllowOfflineMode) { fprintf(stderr, "(offline root mode: not running %s.%s)\n", pkg->name, script); free(path); return 0; @@ -1571,15 +1693,12 @@ int pkg_arch_supported(opkg_conf_t *conf, pkg_t *pkg) if (!pkg->architecture) return 1; - l = conf->arch_list.head; - - while (l) { - nv_pair_t *nv = l->data; + list_for_each_entry(l , &conf->arch_list.head, node) { + nv_pair_t *nv = (nv_pair_t *)l->data; if (strcmp(nv->name, pkg->architecture) == 0) { opkg_message(conf, OPKG_DEBUG, "arch %s (priority %s) supported for pkg %s\n", nv->name, nv->value, pkg->name); return 1; } - l = l->next; } opkg_message(conf, OPKG_DEBUG, "arch %s unsupported for pkg %s\n", pkg->architecture, pkg->name); @@ -1590,15 +1709,12 @@ int pkg_get_arch_priority(opkg_conf_t *conf, const char *archname) { nv_pair_list_elt_t *l; - l = conf->arch_list.head; - - while (l) { - nv_pair_t *nv = l->data; + list_for_each_entry(l , &conf->arch_list.head, node) { + nv_pair_t *nv = (nv_pair_t *)l->data; if (strcmp(nv->name, archname) == 0) { int priority = strtol(nv->value, NULL, 0); return priority; } - l = l->next; } return 0; } @@ -1631,7 +1747,7 @@ int pkg_info_preinstall_check(opkg_conf_t *conf) pkg_t *pkg = available_pkgs->pkgs[i]; if (!pkg->arch_priority && (pkg->state_flag || (pkg->state_want != SW_UNKNOWN))) { /* clear flags and want for any uninstallable package */ - opkg_message(conf, OPKG_NOTICE, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n", + opkg_message(conf, OPKG_DEBUG, "Clearing state_want and state_flag for pkg=%s (arch_priority=%d flag=%d want=%d)\n", pkg->name, pkg->arch_priority, pkg->state_flag, pkg->state_want); pkg->state_want = SW_UNKNOWN; pkg->state_flag = 0; @@ -1650,11 +1766,12 @@ int pkg_info_preinstall_check(opkg_conf_t *conf) opkg_message(conf, OPKG_ERROR, "No installed files for pkg %s\n", pkg->name); break; } - for (iter = installed_files->head; iter; iter = iter->next) { - char *installed_file = iter->data; + for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) { + char *installed_file = (char *) iter->data; // opkg_message(conf, OPKG_DEBUG2, "pkg %s: file=%s\n", pkg->name, installed_file); file_hash_set_file_owner(conf, installed_file, pkg); } + pkg_free_installed_files(pkg); } pkg_vec_free(installed_pkgs); @@ -1707,6 +1824,8 @@ int pkg_write_filelist(opkg_conf_t *conf, pkg_t *pkg) fclose(data.stream); free(list_file_name); + pkg->state_flag &= ~SF_FILELIST_CHANGED; + return err; } @@ -1730,5 +1849,6 @@ int pkg_write_changed_filelists(opkg_conf_t *conf) opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err); } } + pkg_vec_free (installed_pkgs); return 0; }