-/* pkg.c - the itsy package management system
+/* pkg.c - the opkg package management system
Carl D. Worth
General Public License for more details.
*/
-#include "opkg.h"
+#include "includes.h"
#include <ctype.h>
#include <string.h>
+#include <stdbool.h>
#include <errno.h>
#include "pkg.h"
pkg->epoch = 0;
pkg->version = NULL;
pkg->revision = NULL;
- pkg->familiar_revision = NULL;
pkg->dest = NULL;
pkg->src = NULL;
pkg->architecture = NULL;
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 */
pkg->state_want = SW_UNKNOWN;
pkg->state_flag = SF_OK;
pkg->state_status = SS_NOT_INSTALLED;
+
+ //for (i = 0; i < pkg->replaces_count; i++)
+ 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);
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)
strncat(buff ,line, strlen(line));
free(line);
+ line = pkg_formatted_field(pkg, "Tags");
+ strncat(buff ,line, strlen(line));
+ free(line);
+
return buff;
}
}
}
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 */
void pkg_print_info(pkg_t *pkg, FILE *file)
{
+ int t=0;
char * buff;
if (pkg == NULL) {
return;
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);
}
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
return r;
}
-#ifdef USE_DEBVERSION
r = verrevcmp(pkg->revision, ref_pkg->revision);
if (r) {
return r;
}
- r = verrevcmp(pkg->familiar_revision, ref_pkg->familiar_revision);
-#endif
-
return r;
}
-int verrevcmp(const char *val, const char *ref)
-{
- int vc, rc;
- long vl, rl;
- const char *vp, *rp;
- const char *vsep, *rsep;
-
- if (!val) val= "";
- if (!ref) ref= "";
- for (;;) {
- vp= val; while (*vp && !isdigit(*vp)) vp++;
- rp= ref; while (*rp && !isdigit(*rp)) rp++;
- for (;;) {
- vc= (val == vp) ? 0 : *val++;
- rc= (ref == rp) ? 0 : *ref++;
- if (!rc && !vc) break;
- if (vc && !isalpha(vc)) vc += 256; /* assumes ASCII character set */
- if (rc && !isalpha(rc)) rc += 256;
- if (vc != rc) return vc - rc;
- }
- val= vp;
- ref= rp;
- vl=0; if (isdigit(*vp)) vl= strtol(val,(char**)&val,10);
- rl=0; if (isdigit(*rp)) rl= strtol(ref,(char**)&ref,10);
- if (vl != rl) return vl - rl;
-
- vc = *val;
- rc = *ref;
- vsep = strchr(".-", vc);
- rsep = strchr(".-", rc);
- if (vsep && !rsep) return -1;
- if (!vsep && rsep) return +1;
-
- if (!*val && !*ref) return 0;
- if (!*val) return -1;
- if (!*ref) return +1;
- }
+/* assume ascii; warning: evaluates x multiple times! */
+#define order(x) ((x) == '~' ? -1 \
+ : isdigit((x)) ? 0 \
+ : !(x) ? 0 \
+ : isalpha((x)) ? (x) \
+ : (x) + 256)
+
+static int verrevcmp(const char *val, const char *ref) {
+ if (!val) val= "";
+ if (!ref) ref= "";
+
+ while (*val || *ref) {
+ int first_diff= 0;
+
+ while ( (*val && !isdigit(*val)) || (*ref && !isdigit(*ref)) ) {
+ int vc= order(*val), rc= order(*ref);
+ if (vc != rc) return vc - rc;
+ val++; ref++;
+ }
+
+ while ( *val == '0' ) val++;
+ while ( *ref == '0' ) ref++;
+ while (isdigit(*val) && isdigit(*ref)) {
+ if (!first_diff) first_diff= *val - *ref;
+ val++; ref++;
+ }
+ if (isdigit(*val)) return 1;
+ if (isdigit(*ref)) return -1;
+ if (first_diff) return first_diff;
+ }
+ return 0;
}
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) {
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;
{
char *complete_version;
char *epoch_str;
-#ifdef USE_DEBVERSION
char *revision_str;
- char *familiar_revision_str;
-#endif
if (pkg->epoch) {
sprintf_alloc(&epoch_str, "%d:", pkg->epoch);
epoch_str = strdup("");
}
-#ifdef USE_DEBVERSION
if (pkg->revision && strlen(pkg->revision)) {
sprintf_alloc(&revision_str, "-%s", pkg->revision);
} else {
revision_str = strdup("");
}
- if (pkg->familiar_revision && strlen(pkg->familiar_revision)) {
- sprintf_alloc(&familiar_revision_str, "-fam%s", pkg->familiar_revision);
- } else {
- familiar_revision_str = strdup("");
- }
-#endif
-#ifdef USE_DEBVERSION
- sprintf_alloc(&complete_version, "%s%s%s%s",
- epoch_str, pkg->version, revision_str, familiar_revision_str);
-#else
- sprintf_alloc(&complete_version, "%s%s",
- epoch_str, pkg->version);
-#endif
+ sprintf_alloc(&complete_version, "%s%s%s",
+ epoch_str, pkg->version, revision_str);
free(epoch_str);
-#ifdef USE_DEBVERSION
free(revision_str);
- free(familiar_revision_str);
-#endif
return complete_version;
}
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) {
}
str_list_deinit(pkg->installed_files);
+ free (pkg->installed_files);
}
pkg->installed_files = NULL;
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",
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;
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;
// 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);
opkg_message(conf, OPKG_NOTICE, "pkg_write_filelist pkg=%s returned %d\n", pkg->name, err);
}
}
+ pkg_vec_free (installed_pkgs);
return 0;
}