diff options
Diffstat (limited to 'recipes/ipkg')
34 files changed, 1010 insertions, 0 deletions
diff --git a/recipes/ipkg/files/1-pkg-parse--Optimize-inefficient-parsing.patch b/recipes/ipkg/files/1-pkg-parse--Optimize-inefficient-parsing.patch new file mode 100644 index 0000000000..e7632b11d1 --- /dev/null +++ b/recipes/ipkg/files/1-pkg-parse--Optimize-inefficient-parsing.patch @@ -0,0 +1,227 @@ +# HG changeset patch +# User pfalcon@localhost +# Date 1178334771 0 +# Node ID e4c99830ba0d55813e1774bd6d41039ca640d6a6 +# Parent d324eba24e79a0a86df7978f0511e4632a2732c7 +pkg_parse: Optimize inefficient parsing. + +Instead of expensively probing all fields in row, dispatch based on the +first letter of the field. Tests show ~12 times reduction in number of calls +to low-level parsing functions. + +diff -r d324eba24e79 -r e4c99830ba0d pkg_parse.c +--- a/pkg_parse.c Fri May 04 23:22:33 2007 +0000 ++++ b/pkg_parse.c Sat May 05 03:12:51 2007 +0000 +@@ -241,87 +241,116 @@ int pkg_parse_raw(pkg_t *pkg, char ***ra + + for (lines = *raw; *lines; lines++) { + /* fprintf(stderr, "PARSING %s\n", *lines);*/ +- if(isGenericFieldType("Package:", *lines)) +- pkg->name = parseGenericFieldType("Package", *lines); +- else if(isGenericFieldType("Architecture:", *lines)) +- pkg->architecture = parseGenericFieldType("Architecture", *lines); +- else if(isGenericFieldType("Filename:", *lines)) +- pkg->filename = parseGenericFieldType("Filename", *lines); +- else if(isGenericFieldType("Section:", *lines)) +- pkg->section = parseGenericFieldType("Section", *lines); +- else if(isGenericFieldType("MD5sum:", *lines)) +- pkg->md5sum = parseGenericFieldType("MD5sum", *lines); +- /* The old ipkg wrote out status files with the wrong case for MD5sum, +- let's parse it either way */ +- else if(isGenericFieldType("MD5Sum:", *lines)) +- pkg->md5sum = parseGenericFieldType("MD5Sum", *lines); +- else if(isGenericFieldType("Size:", *lines)) +- pkg->size = parseGenericFieldType("Size", *lines); +- else if(isGenericFieldType("Source:", *lines)) +- pkg->source = parseGenericFieldType("Source", *lines); +- else if(isGenericFieldType("Installed-Size:", *lines)) +- pkg->installed_size = parseGenericFieldType("Installed-Size", *lines); +- else if(isGenericFieldType("Installed-Time:", *lines)) { +- char *time_str = parseGenericFieldType("Installed-Time", *lines); +- pkg->installed_time = strtoul(time_str, NULL, 0); +- } else if(isGenericFieldType("Priority:", *lines)) +- pkg->priority = parseGenericFieldType("Priority", *lines); +- else if(isGenericFieldType("Essential:", *lines)) { +- char *essential_value; +- essential_value = parseGenericFieldType("Essential", *lines); +- if (strcmp(essential_value, "yes") == 0) { +- pkg->essential = 1; +- } +- free(essential_value); +- } +- else if(isGenericFieldType("Status", *lines)) +- parseStatus(pkg, *lines); +- else if(isGenericFieldType("Version", *lines)) +- parseVersion(pkg, *lines); +- else if(isGenericFieldType("Maintainer", *lines)) +- pkg->maintainer = parseGenericFieldType("Maintainer", *lines); +- else if(isGenericFieldType("Conffiles", *lines)){ +- parseConffiles(pkg, *lines); +- reading_conffiles = 1; +- } +- else if(isGenericFieldType("Description", *lines)) { +- pkg->description = parseGenericFieldType("Description", *lines); +- reading_conffiles = 0; +- reading_description = 1; +- } +- +- else if(isGenericFieldType("Provides", *lines)){ ++ switch (**lines) { ++ case 'P': ++ if(isGenericFieldType("Package:", *lines)) ++ pkg->name = parseGenericFieldType("Package", *lines); ++ else if(isGenericFieldType("Priority:", *lines)) ++ pkg->priority = parseGenericFieldType("Priority", *lines); ++ else if(isGenericFieldType("Provides", *lines)){ + /* Here we add the internal_use to align the off by one problem between provides_str and provides */ +- provide = (char * ) malloc(strlen(*lines)+ 35 ); /* Preparing the space for the new ipkg_internal_use_only */ +- if ( alterProvidesLine(*lines,provide) ){ +- return EINVAL; +- } +- pkg->provides_str = parseDependsString( provide, &pkg->provides_count); ++ provide = (char * ) malloc(strlen(*lines)+ 35 ); /* Preparing the space for the new ipkg_internal_use_only */ ++ if ( alterProvidesLine(*lines,provide) ){ ++ return EINVAL; ++ } ++ pkg->provides_str = parseDependsString( provide, &pkg->provides_count); + /* Let's try to hack a bit here. + The idea is that if a package has no Provides, we would add one generic, to permit the check of dependencies + in alot of other places. We will remove it before writing down the status database */ +- pkg_false_provides=0; +- free(provide); +- } +- +- else if(isGenericFieldType("Depends", *lines)) +- pkg->depends_str = parseDependsString(*lines, &pkg->depends_count); +- else if(isGenericFieldType("Pre-Depends", *lines)) +- pkg->pre_depends_str = parseDependsString(*lines, &pkg->pre_depends_count); +- else if(isGenericFieldType("Recommends", *lines)) +- pkg->recommends_str = parseDependsString(*lines, &pkg->recommends_count); +- else if(isGenericFieldType("Suggests", *lines)) +- pkg->suggests_str = parseDependsString(*lines, &pkg->suggests_count); +- /* Abhaya: support for conflicts */ +- else if(isGenericFieldType("Conflicts", *lines)) +- pkg->conflicts_str = parseDependsString(*lines, &pkg->conflicts_count); +- else if(isGenericFieldType("Replaces", *lines)) +- pkg->replaces_str = parseDependsString(*lines, &pkg->replaces_count); +- else if(line_is_blank(*lines)) { +- lines++; +- break; +- } +- else if(**lines == ' '){ ++ pkg_false_provides=0; ++ free(provide); ++ } ++ else if(isGenericFieldType("Pre-Depends", *lines)) ++ pkg->pre_depends_str = parseDependsString(*lines, &pkg->pre_depends_count); ++ break; ++ ++ case 'A': ++ if(isGenericFieldType("Architecture:", *lines)) ++ pkg->architecture = parseGenericFieldType("Architecture", *lines); ++ break; ++ ++ case 'F': ++ if(isGenericFieldType("Filename:", *lines)) ++ pkg->filename = parseGenericFieldType("Filename", *lines); ++ break; ++ ++ case 'S': ++ if(isGenericFieldType("Section:", *lines)) ++ pkg->section = parseGenericFieldType("Section", *lines); ++ else if(isGenericFieldType("Size:", *lines)) ++ pkg->size = parseGenericFieldType("Size", *lines); ++ else if(isGenericFieldType("Source:", *lines)) ++ pkg->source = parseGenericFieldType("Source", *lines); ++ else if(isGenericFieldType("Status", *lines)) ++ parseStatus(pkg, *lines); ++ else if(isGenericFieldType("Suggests", *lines)) ++ pkg->suggests_str = parseDependsString(*lines, &pkg->suggests_count); ++ break; ++ ++ case 'M': ++ if(isGenericFieldType("MD5sum:", *lines)) ++ pkg->md5sum = parseGenericFieldType("MD5sum", *lines); ++ /* The old ipkg wrote out status files with the wrong case for MD5sum, ++ let's parse it either way */ ++ else if(isGenericFieldType("MD5Sum:", *lines)) ++ pkg->md5sum = parseGenericFieldType("MD5Sum", *lines); ++ else if(isGenericFieldType("Maintainer", *lines)) ++ pkg->maintainer = parseGenericFieldType("Maintainer", *lines); ++ break; ++ ++ case 'I': ++ if(isGenericFieldType("Installed-Size:", *lines)) ++ pkg->installed_size = parseGenericFieldType("Installed-Size", *lines); ++ else if(isGenericFieldType("Installed-Time:", *lines)) { ++ char *time_str = parseGenericFieldType("Installed-Time", *lines); ++ pkg->installed_time = strtoul(time_str, NULL, 0); ++ } ++ break; ++ ++ case 'E': ++ if(isGenericFieldType("Essential:", *lines)) { ++ char *essential_value; ++ essential_value = parseGenericFieldType("Essential", *lines); ++ if (strcmp(essential_value, "yes") == 0) { ++ pkg->essential = 1; ++ } ++ free(essential_value); ++ } ++ break; ++ ++ case 'V': ++ if(isGenericFieldType("Version", *lines)) ++ parseVersion(pkg, *lines); ++ break; ++ ++ case 'C': ++ if(isGenericFieldType("Conffiles", *lines)){ ++ parseConffiles(pkg, *lines); ++ reading_conffiles = 1; ++ } ++ else if(isGenericFieldType("Conflicts", *lines)) ++ pkg->conflicts_str = parseDependsString(*lines, &pkg->conflicts_count); ++ break; ++ ++ case 'D': ++ if(isGenericFieldType("Description", *lines)) { ++ pkg->description = parseGenericFieldType("Description", *lines); ++ reading_conffiles = 0; ++ reading_description = 1; ++ } ++ else if(isGenericFieldType("Depends", *lines)) ++ pkg->depends_str = parseDependsString(*lines, &pkg->depends_count); ++ break; ++ ++ case 'R': ++ if(isGenericFieldType("Recommends", *lines)) ++ pkg->recommends_str = parseDependsString(*lines, &pkg->recommends_count); ++ else if(isGenericFieldType("Replaces", *lines)) ++ pkg->replaces_str = parseDependsString(*lines, &pkg->replaces_count); ++ ++ break; ++ ++ case ' ': + if(reading_description) { + /* we already know it's not blank, so the rest of description */ + pkg->description = realloc(pkg->description, +@@ -332,8 +361,18 @@ int pkg_parse_raw(pkg_t *pkg, char ***ra + } + else if(reading_conffiles) + parseConffiles(pkg, *lines); ++ ++ break; ++ ++ default: ++ if(line_is_blank(*lines)) { ++ lines++; ++ goto out; ++ } + } + } ++out:; ++ + *raw = lines; + /* If the ipk has not a Provides line, we insert our false line */ + if ( pkg_false_provides==1) diff --git a/recipes/ipkg/files/2-pkg-vec--Optimize-gross-inefficiency.patch b/recipes/ipkg/files/2-pkg-vec--Optimize-gross-inefficiency.patch new file mode 100644 index 0000000000..3c5cac49dc --- /dev/null +++ b/recipes/ipkg/files/2-pkg-vec--Optimize-gross-inefficiency.patch @@ -0,0 +1,65 @@ +# HG changeset patch +# User pfalcon@localhost +# Date 1178812057 0 +# Node ID eff4450fdea2f8210a4fc927bd35ae2562d2eced +# Parent e4c99830ba0d55813e1774bd6d41039ca640d6a6 +pkg_vec: Optimize gross inefficiency. + +This module tries to implement *unique* vector (without duplicating +objects), and does this by iterating thru all already existing elements. +Thus, complexity of adding N elements was O(N^2). However, there're no grave +reasons to do uniqueness at all: +1. First of all, if feeds are correct, there won't be duplicates. +2. Then, even if there will be, there won't be serious problems like +segfaults. +3. Finally, for quite a few operations vectors is constructed from a +hashtable, thus uniqueness is guaranteed (which reduces possible cases of +non-uniqueness to values of Depends: and friends). + +All an all, remove dup check, and make ipkg work order of magnitude faster +on a feed with few thousands of packages. + +diff -r e4c99830ba0d -r eff4450fdea2 pkg_vec.c +--- a/pkg_vec.c Sat May 05 03:12:51 2007 +0000 ++++ b/pkg_vec.c Thu May 10 15:47:37 2007 +0000 +@@ -104,6 +104,7 @@ void pkg_vec_insert(pkg_vec_t *vec, cons + int i; + int found = 0; + ++#if 0 + /* look for a duplicate pkg by name, version, and architecture */ + for (i = 0; i < vec->len; i++) + if ((strcmp(pkg->name, vec->pkgs[i]->name) == 0) +@@ -112,6 +113,7 @@ void pkg_vec_insert(pkg_vec_t *vec, cons + found = 1; + break; + } ++#endif + + /* we didn't find one, add it */ + if(!found){ +@@ -191,6 +193,7 @@ void abstract_pkg_vec_insert(abstract_pk + { + int i; + ++#if 0 + /* look for a duplicate pkg by name */ + for(i = 0; i < vec->len; i++) + if (strcmp(pkg->name, vec->pkgs[i]->name) == 0) +@@ -198,12 +201,15 @@ void abstract_pkg_vec_insert(abstract_pk + + /* we didn't find one, add it */ + if(i == vec->len){ ++#endif + vec->pkgs = + (abstract_pkg_t **) + realloc(vec->pkgs, (vec->len + 1) * sizeof(abstract_pkg_t *)); + vec->pkgs[vec->len] = pkg; + vec->len++; +- } ++#if 0 ++ } ++#endif + } + + abstract_pkg_t * abstract_pkg_vec_get(abstract_pkg_vec_t *vec, int i) diff --git a/recipes/ipkg/files/enable_debversion.patch b/recipes/ipkg/files/enable_debversion.patch new file mode 100644 index 0000000000..e9c3a7a1d4 --- /dev/null +++ b/recipes/ipkg/files/enable_debversion.patch @@ -0,0 +1,111 @@ +OE makes heavy use of the revision field so it makes sense to +enable it. We don't want the familiar stuff though so patch that +out. + +RP - 19/02/2008 + +Index: ipkg-0.99.163/pkg.c +=================================================================== +--- ipkg-0.99.163.orig/pkg.c 2008-02-19 00:35:03.000000000 +0000 ++++ ipkg-0.99.163/pkg.c 2008-02-19 00:36:02.000000000 +0000 +@@ -1118,15 +1118,11 @@ + 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; + } + +@@ -1240,10 +1236,7 @@ + { + 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); +@@ -1251,33 +1244,18 @@ + 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; + } +Index: ipkg-0.99.163/pkg_parse.c +=================================================================== +--- ipkg-0.99.163.orig/pkg_parse.c 2008-02-19 00:35:03.000000000 +0000 ++++ ipkg-0.99.163/pkg_parse.c 2008-02-19 00:38:42.000000000 +0000 +@@ -105,9 +105,7 @@ + int parseVersion(pkg_t *pkg, char *raw) + { + char *colon, *eepochcolon; +-#ifdef USE_DEBVERSION + char *hyphen; +-#endif + unsigned long epoch; + + if (!*raw) { +@@ -149,23 +147,12 @@ + } + strcpy(pkg->version, raw); + +-#ifdef USE_DEBVERSION + hyphen= strrchr(pkg->version,'-'); + + if (hyphen) { + *hyphen++= 0; +- if (strncmp("fam", hyphen, 3) == 0) { +- pkg->familiar_revision=hyphen+3; +- hyphen= strrchr(pkg->version,'-'); +- if (hyphen) { +- *hyphen++= 0; +- pkg->revision = hyphen; +- } +- } else { + pkg->revision = hyphen; +- } + } +-#endif + + /* + fprintf(stderr,"Parsed version: %lu, %s, %s, %s\n", diff --git a/recipes/ipkg/files/ipkg-configure b/recipes/ipkg/files/ipkg-configure new file mode 100644 index 0000000000..e0c65ad4e2 --- /dev/null +++ b/recipes/ipkg/files/ipkg-configure @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "Starting to configure packages..." +ipkg-cl configure +echo "Finished to configure packages." diff --git a/recipes/ipkg/files/is-processing.patch b/recipes/ipkg/files/is-processing.patch new file mode 100644 index 0000000000..45ede41668 --- /dev/null +++ b/recipes/ipkg/files/is-processing.patch @@ -0,0 +1,179 @@ +diff -Nur ipkg-0.99.163.orig/ipkg_install.c ipkg-0.99.163/ipkg_install.c +--- ipkg-0.99.163.orig/ipkg_install.c 2006-03-30 21:50:24.000000000 +0800 ++++ ipkg-0.99.163/ipkg_install.c 2007-03-15 08:01:20.000000000 +0800 +@@ -211,6 +211,7 @@ + anyone ever wants to make a nice libipkg. */ + + ipkg_message(conf, IPKG_DEBUG2,"Function: %s calling ipkg_install_pkg \n",__FUNCTION__); ++ new->is_processing = 1; + return ipkg_install_pkg(conf, new,0); + } + +diff -Nur ipkg-0.99.163.orig/libbb/unzip.c ipkg-0.99.163/libbb/unzip.c +--- ipkg-0.99.163.orig/libbb/unzip.c 2006-02-06 16:13:02.000000000 +0800 ++++ ipkg-0.99.163/libbb/unzip.c 2007-03-15 08:03:45.000000000 +0800 +@@ -1028,13 +1028,15 @@ + */ + extern void gz_close(int gunzip_pid) + { +- if (kill(gunzip_pid, SIGTERM) == -1) { +- error_msg_and_die("*** Couldnt kill old gunzip process *** aborting"); +- } ++ if (kill(gunzip_pid, 0) == 0) { ++ if (kill(gunzip_pid, SIGTERM) == -1) { ++ error_msg_and_die("*** Couldnt kill old gunzip process *** aborting"); ++ } + +- if (waitpid(gunzip_pid, NULL, 0) == -1) { +- printf("Couldnt wait ?"); ++ if (waitpid(gunzip_pid, NULL, 0) == -1) { ++ printf("Couldnt wait ?"); ++ } + } +- free(window); +- free(crc_table); ++ free(window); ++ free(crc_table); + } +diff -Nur ipkg-0.99.163.orig/pkg.c ipkg-0.99.163/pkg.c +--- ipkg-0.99.163.orig/pkg.c 2006-04-21 04:29:28.000000000 +0800 ++++ ipkg-0.99.163/pkg.c 2007-03-20 15:11:32.845064480 +0800 +@@ -33,6 +33,7 @@ + #include "xsystem.h" + #include "ipkg_conf.h" + ++ + typedef struct enum_map enum_map_t; + struct enum_map + { +@@ -522,6 +523,10 @@ + strncat(buff ,line, strlen(line)); + free(line); + ++ line = pkg_formatted_field(pkg, "Installed-Size"); ++ strncat(buff ,line, strlen(line)); ++ free(line); ++ + return buff; + } + +@@ -542,7 +547,6 @@ + } + + temp[0]='\0'; +- + switch (field[0]) + { + case 'a': +@@ -690,13 +694,42 @@ + case 'I': { + if (strcasecmp(field, "Installed-Size") == 0) { + /* Installed-Size */ +- temp = (char *)realloc(temp,strlen(pkg->installed_size)+17); +- if ( temp == NULL ){ +- fprintf(stderr, "%s: out of memory\n", __FUNCTION__); +- return NULL; +- } +- temp[0]='\0'; +- snprintf(temp, (strlen(pkg->installed_size)+17), "Installed-Size: %s\n", pkg->installed_size); ++ if (pkg->installed_size) { ++ temp = (char *)realloc(temp,strlen(pkg->installed_size)+18); ++ if ( temp == NULL ){ ++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__); ++ return NULL; ++ } ++ temp[0]='\0'; ++ snprintf(temp, (strlen(pkg->installed_size)+18), "Installed-Size: %s\n", pkg->installed_size); ++ } else { ++ /* Caculate installed files size */ ++ str_list_elt_t *iter; ++ struct stat buf; ++ int installed_files_length = 0; ++ if (pkg->installed_files == NULL) ++ break; ++ ++ if (pkg->is_processing!=1) ++ break; ++ ++ for (iter = pkg->installed_files->head; iter; iter = iter->next) { ++ memset(&buf, 0, sizeof(struct stat)); ++ stat(iter->data, &buf); ++ if (S_ISREG(buf.st_mode)) ++ installed_files_length += buf.st_size; ++ } ++ /*printf("installed_files_length:%d\n", installed_files_length);*/ ++ ++ sprintf_alloc(&pkg->installed_size, "%d", installed_files_length); ++ temp = (char *)realloc(temp,strlen(pkg->installed_size)+18); ++ if ( temp == NULL ){ ++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__); ++ return NULL; ++ } ++ temp[0]='\0'; ++ snprintf(temp, (strlen(pkg->installed_size)+18), "Installed-Size: %s\n", pkg->installed_size); ++ } + } else if (strcasecmp(field, "Installed-Time") == 0 && pkg->installed_time) { + temp = (char *)realloc(temp,29); + if ( temp == NULL ){ +@@ -720,7 +753,7 @@ + return NULL; + } + temp[0]='\0'; +- snprintf(temp, (strlen(pkg->maintainer)+14), "maintainer: %s\n", pkg->maintainer); ++ snprintf(temp, (strlen(pkg->maintainer)+14), "Maintainer: %s\n", pkg->maintainer); + } + } else if (strcasecmp(field, "MD5sum") == 0) { + /* MD5sum */ +@@ -871,6 +904,24 @@ + } + temp[0]='\0'; + snprintf(temp, (strlen(pkg->size)+8), "Size: %s\n", pkg->size); ++ } else { ++ if ( pkg->local_filename ) { ++ struct stat buf; ++ memset(&buf, 0, sizeof(struct stat)); ++ ++ if ( stat(pkg->local_filename, &buf) == 0 ) { ++ ++ sprintf_alloc(&pkg->size, "%d", buf.st_size); ++ temp = (char *)realloc(temp, strlen(pkg->size)+8); ++ if ( temp == NULL ){ ++ fprintf(stderr, "%s: out of memory\n", __FUNCTION__); ++ return NULL; ++ } ++ temp[0]='\0'; ++ snprintf(temp, (strlen(pkg->size)+8), "Size: %s\n", pkg->size); ++ } ++ } ++ + } + } else if (strcasecmp(field, "Source") == 0) { + /* Source */ +@@ -1016,6 +1067,12 @@ + pkg_print_field(pkg, file, "Essential"); /* @@@@ should be removed in future release. */ + pkg_print_field(pkg, file, "Architecture"); + pkg_print_field(pkg, file, "Conffiles"); ++ pkg_print_field(pkg, file, "Description"); ++ pkg_print_field(pkg, file, "Maintainer"); ++ pkg_print_field(pkg, file, "Section"); ++ pkg_print_field(pkg, file, "Size"); ++ pkg_print_field(pkg, file, "Filename"); ++ pkg_print_field(pkg, file, "Installed-Size"); + pkg_print_field(pkg, file, "Installed-Time"); + fputs("\n", file); + } +diff -Nur ipkg-0.99.163.orig/pkg.h ipkg-0.99.163/pkg.h +--- ipkg-0.99.163.orig/pkg.h 2006-05-30 16:31:08.000000000 +0800 ++++ ipkg-0.99.163/pkg.h 2007-03-15 08:01:20.000000000 +0800 +@@ -176,6 +176,10 @@ + int arch_priority; + /* Adding this flag, to "force" ipkg to choose a "provided_by_hand" package, if there are multiple choice */ + int provided_by_hand; ++ ++ /* Check whether this pkg is being removed or installed */ ++ int is_processing; ++ + }; + + pkg_t *pkg_new(void); +
diff --git a/recipes/ipkg/files/libdir.patch b/recipes/ipkg/files/libdir.patch new file mode 100644 index 0000000000..38f0b4d286 --- /dev/null +++ b/recipes/ipkg/files/libdir.patch @@ -0,0 +1,11 @@ +--- C/ipkg.h.in.old 2005-04-02 17:11:02.762413624 +0100 ++++ C/ipkg.h.in 2005-04-02 17:11:06.314873568 +0100 +@@ -36,7 +36,7 @@ + #define IPKG_LEGAL_PKG_NAME_CHARS "abcdefghijklmnopqrstuvwxyz0123456789.+-" + #define IPKG_PKG_VERSION_SEP_CHAR '_' + +-#define IPKG_STATE_DIR_PREFIX LIBDIR"/ipkg" ++#define IPKG_STATE_DIR_PREFIX "/usr/lib/ipkg" + #define IPKG_LISTS_DIR_SUFFIX "lists" + #define IPKG_INFO_DIR_SUFFIX "info" + #define IPKG_STATUS_FILE_SUFFIX "status" diff --git a/recipes/ipkg/files/lonk-link-name.patch b/recipes/ipkg/files/lonk-link-name.patch new file mode 100644 index 0000000000..14fc73a5ac --- /dev/null +++ b/recipes/ipkg/files/lonk-link-name.patch @@ -0,0 +1,38 @@ +--- ipkg-0.99.163/libbb/unarchive.c.orig 2007-10-04 12:39:42.000000000 +0200 ++++ ipkg-0.99.163/libbb/unarchive.c 2007-10-04 12:41:28.000000000 +0200 +@@ -595,10 +595,6 @@ + if (longname) { + tar_entry->name = longname; + longname = NULL; +- } +- else if (linkname) { +- tar_entry->name = linkname; +- linkname = NULL; + } else + #endif + if (tar.formated.prefix[0] == 0) { +@@ -606,6 +602,15 @@ + } else { + tar_entry->name = concat_path_file(tar.formated.prefix, tar.formated.name); + } ++ ++#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS ++ if (linkname) { ++ tar_entry->link_name = linkname; ++ linkname = NULL; ++ } else ++#endif ++ tar_entry->link_name = strlen(tar.formated.linkname) ? ++ xstrdup(tar.formated.linkname) : NULL; + + // tar_entry->name = xstrdup(tar.formated.name); + +@@ -618,8 +623,6 @@ + tar_entry->gid = strtol(tar.formated.gid, NULL, 8); + tar_entry->size = strtol(tar.formated.size, NULL, 8); + tar_entry->mtime = strtol(tar.formated.mtime, NULL, 8); +- tar_entry->link_name = strlen(tar.formated.linkname) ? +- xstrdup(tar.formated.linkname) : NULL; + tar_entry->device = (strtol(tar.formated.devmajor, NULL, 8) << 8) + + strtol(tar.formated.devminor, NULL, 8); + diff --git a/recipes/ipkg/files/terse.patch b/recipes/ipkg/files/terse.patch new file mode 100644 index 0000000000..3c4d6bed7e --- /dev/null +++ b/recipes/ipkg/files/terse.patch @@ -0,0 +1,18 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- C/ipkg_cmd.c~terse ++++ C/ipkg_cmd.c +@@ -148,9 +146,7 @@ + int result; + p_userdata = userdata; + result = (cmd->fun)(conf, argc, argv); +- if ( result == 0 ) { +- ipkg_message(conf, IPKG_NOTICE, "Successfully terminated.\n"); +- } else { ++ if ( result != 0 ) { + ipkg_message(conf, IPKG_NOTICE, "An error ocurred, return value: %d.\n", result); + } + diff --git a/recipes/ipkg/files/uclibc.patch b/recipes/ipkg/files/uclibc.patch new file mode 100644 index 0000000000..d0d3a3ff7c --- /dev/null +++ b/recipes/ipkg/files/uclibc.patch @@ -0,0 +1,13 @@ +Index: C/libbb/libbb.h +=================================================================== +--- C.orig/libbb/libbb.h 2003-02-24 10:31:52.000000000 -0500 ++++ C/libbb/libbb.h 2005-01-20 03:07:10.031420944 -0500 +@@ -340,7 +340,7 @@ + #define CONSOLE_DEV "/dev/console" + + /* Cope with mmu-less systems somewhat gracefully */ +-#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__) ++#if defined(__UCLIBC__) && !defined(__ARCH_HAS_MMU__) + #define fork vfork + #endif + diff --git a/recipes/ipkg/files/uninclude-replace.patch b/recipes/ipkg/files/uninclude-replace.patch new file mode 100644 index 0000000000..a3ed2201fd --- /dev/null +++ b/recipes/ipkg/files/uninclude-replace.patch @@ -0,0 +1,10 @@ +--- C/includes.h 2003-03-28 19:36:22.000000000 +0000 ++++ C/includes.h 2004-07-28 03:41:11.000000000 +0100 +@@ -48,6 +48,6 @@ + # include <unistd.h> + #endif + +-#include "replace/replace.h" ++//#include "replace/replace.h" + + #endif diff --git a/recipes/ipkg/files/update_version_comparision.patch b/recipes/ipkg/files/update_version_comparision.patch new file mode 100644 index 0000000000..b0d0df525b --- /dev/null +++ b/recipes/ipkg/files/update_version_comparision.patch @@ -0,0 +1,84 @@ +Update the version comparision to a more recent one from dpkg. This +means it now recognises 0.0-foo > 0.0+foo as it should. + +RP - 19/02/2008 + +Index: ipkg-0.99.163/pkg.c +=================================================================== +--- ipkg-0.99.163.orig/pkg.c 2008-02-18 11:24:45.000000000 +0000 ++++ ipkg-0.99.163/pkg.c 2008-02-19 00:24:50.000000000 +0000 +@@ -1128,43 +1130,37 @@ + 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) diff --git a/recipes/ipkg/ipkg-0.99.163/patch-ipkg-localfilename b/recipes/ipkg/ipkg-0.99.163/patch-ipkg-localfilename new file mode 100644 index 0000000000..41f17fd954 --- /dev/null +++ b/recipes/ipkg/ipkg-0.99.163/patch-ipkg-localfilename @@ -0,0 +1,29 @@ +--- ipkg-0.99.163.orig/ipkg_download.c Thu Apr 20 20:18:29 2006 ++++ ipkg-0.99.163/ipkg_download.c Thu Jan 18 05:54:52 2007 +@@ -108,6 +108,7 @@ + { + int err; + char *url; ++ char *filename; + + if (pkg->src == NULL) { + ipkg_message(conf,IPKG_ERROR, "ERROR: Package %s (parent %s) is not available from any configured src.\n", +@@ -117,11 +118,16 @@ + + sprintf_alloc(&url, "%s/%s", pkg->src->value, pkg->filename); + +- /* XXX: BUG: The pkg->filename might be something like ++ /* The pkg->filename might be something like + "../../foo.ipk". While this is correct, and exactly what we + want to use to construct url above, here we actually need to + use just the filename part, without any directory. */ +- sprintf_alloc(&pkg->local_filename, "%s/%s", dir, pkg->filename); ++ filename = strrchr(pkg->filename, '/'); ++ if(NULL == filename) ++ filename = pkg->filename; ++ else ++ filename++; ++ sprintf_alloc(&pkg->local_filename, "%s/%s", dir, filename); + + err = ipkg_download(conf, url, pkg->local_filename); + free(url); diff --git a/recipes/ipkg/ipkg-collateral.bb b/recipes/ipkg/ipkg-collateral.bb new file mode 100644 index 0000000000..3fd55507e2 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral.bb @@ -0,0 +1,25 @@ +DESCRIPTION = "ipkg configuration files" +SECTION = "base" +LICENSE = "MIT" +PR = "r7" + +SRC_URI = " \ +file://ipkg.conf.comments \ +file://lists \ +file://dest \ +file://src \ +" + +do_compile () { + cat ${WORKDIR}/ipkg.conf.comments >${WORKDIR}/ipkg.conf + cat ${WORKDIR}/src >>${WORKDIR}/ipkg.conf + cat ${WORKDIR}/dest >>${WORKDIR}/ipkg.conf + cat ${WORKDIR}/lists >>${WORKDIR}/ipkg.conf +} + +do_install () { + install -d ${D}${sysconfdir}/ + install -m 0644 ${WORKDIR}/ipkg.conf ${D}${sysconfdir}/ipkg.conf +} + +CONFFILES_${PN} = "${sysconfdir}/ipkg.conf" diff --git a/recipes/ipkg/ipkg-collateral/akita/dest b/recipes/ipkg/ipkg-collateral/akita/dest new file mode 100644 index 0000000000..647490d30a --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/akita/dest @@ -0,0 +1,4 @@ +dest root / +dest home /home/packages/ +dest cf /media/cf/packages/ +dest sd /media/card/packages/ diff --git a/recipes/ipkg/ipkg-collateral/akita/lists b/recipes/ipkg/ipkg-collateral/akita/lists new file mode 100644 index 0000000000..cc776c595b --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/akita/lists @@ -0,0 +1,4 @@ + +# Uncomment to move ipkg server-data into RAM +# lists_dir ext /var/lib/ipkg + diff --git a/recipes/ipkg/ipkg-collateral/collie/dest b/recipes/ipkg/ipkg-collateral/collie/dest new file mode 100644 index 0000000000..c76101a5b2 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/collie/dest @@ -0,0 +1,4 @@ +dest root / +dest cf /media/cf/packages/ +dest sd /media/card/packages/ +dest ram /media/ram/packages/ diff --git a/recipes/ipkg/ipkg-collateral/dest b/recipes/ipkg/ipkg-collateral/dest new file mode 100644 index 0000000000..088ca403da --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/dest @@ -0,0 +1 @@ +dest root / diff --git a/recipes/ipkg/ipkg-collateral/ipkg.conf.comments b/recipes/ipkg/ipkg-collateral/ipkg.conf.comments new file mode 100644 index 0000000000..51623f4d53 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/ipkg.conf.comments @@ -0,0 +1,23 @@ +# Must have one or more source entries of the form: +# +# src <src-name> <source-url> +# +# and one or more destination entries of the form: +# +# dest <dest-name> <target-path> +# +# where <src-name> and <dest-names> are identifiers that +# should match [a-zA-Z0-9._-]+, <source-url> should be a +# URL that points to a directory containing a Familiar +# Packages file, and <target-path> should be a directory +# that exists on the target system. + +# Proxy Support +#option http_proxy http://proxy.tld:3128 +#option ftp_proxy http://proxy.tld:3128 +#option proxy_username <username> +#option proxy_password <password> + +# Offline mode (for use in constructing flash images offline) +#option offline_root target + diff --git a/recipes/ipkg/ipkg-collateral/jornada56x/dest b/recipes/ipkg/ipkg-collateral/jornada56x/dest new file mode 100644 index 0000000000..154ce57587 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/jornada56x/dest @@ -0,0 +1,4 @@ +dest root / +dest cf /mnt/cf/packages/ +dest sd /mnt/card/packages/ +dest ram /mnt/ram/packages/ diff --git a/recipes/ipkg/ipkg-collateral/lists b/recipes/ipkg/ipkg-collateral/lists new file mode 100644 index 0000000000..3c524f8c77 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/lists @@ -0,0 +1,2 @@ +lists_dir ext /var/lib/ipkg + diff --git a/recipes/ipkg/ipkg-collateral/mx31moboard/dest b/recipes/ipkg/ipkg-collateral/mx31moboard/dest new file mode 100644 index 0000000000..8a5e2659dc --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/mx31moboard/dest @@ -0,0 +1,3 @@ +dest root / +dest sd0 /media/card0/packages/ +dest sd1 /media/card1/packages diff --git a/recipes/ipkg/ipkg-collateral/mx31moboard/src b/recipes/ipkg/ipkg-collateral/mx31moboard/src new file mode 100644 index 0000000000..8e6e50ddca --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/mx31moboard/src @@ -0,0 +1,4 @@ +src/gz local-all file:/media/feeds/all +src/gz local-armv6 file:/media/feeds/armv6 +src/gz local-mx31moboard file:/media/feeds/mx31moboard + diff --git a/recipes/ipkg/ipkg-collateral/openmn/src b/recipes/ipkg/ipkg-collateral/openmn/src new file mode 100644 index 0000000000..97cdd4741c --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/openmn/src @@ -0,0 +1 @@ +src mnci54 http://www.mn-solutions.de/feed/mnci54/base diff --git a/recipes/ipkg/ipkg-collateral/oplinux-uclibc/dest b/recipes/ipkg/ipkg-collateral/oplinux-uclibc/dest new file mode 100644 index 0000000000..b786746b63 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/oplinux-uclibc/dest @@ -0,0 +1,3 @@ +dest root / +dest ram /tmp +dest smbfs /tmp/smbfs diff --git a/recipes/ipkg/ipkg-collateral/oplinux/dest b/recipes/ipkg/ipkg-collateral/oplinux/dest new file mode 100644 index 0000000000..b786746b63 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/oplinux/dest @@ -0,0 +1,3 @@ +dest root / +dest ram /tmp +dest smbfs /tmp/smbfs diff --git a/recipes/ipkg/ipkg-collateral/poodle/dest b/recipes/ipkg/ipkg-collateral/poodle/dest new file mode 100644 index 0000000000..9379964e57 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/poodle/dest @@ -0,0 +1,4 @@ +dest root / +dest cf /media/cf/packages/ +dest sd /media/card/packages/ +dest home /home/packages/ diff --git a/recipes/ipkg/ipkg-collateral/simpad/dest b/recipes/ipkg/ipkg-collateral/simpad/dest new file mode 100644 index 0000000000..20d03ba822 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/simpad/dest @@ -0,0 +1,3 @@ +dest root / +dest cf /mnt/cf/packages/ +dest ram /mnt/ram/packages/ diff --git a/recipes/ipkg/ipkg-collateral/src b/recipes/ipkg/ipkg-collateral/src new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/src diff --git a/recipes/ipkg/ipkg-collateral/tosa/dest b/recipes/ipkg/ipkg-collateral/tosa/dest new file mode 100644 index 0000000000..c76101a5b2 --- /dev/null +++ b/recipes/ipkg/ipkg-collateral/tosa/dest @@ -0,0 +1,4 @@ +dest root / +dest cf /media/cf/packages/ +dest sd /media/card/packages/ +dest ram /media/ram/packages/ diff --git a/recipes/ipkg/ipkg-native.inc b/recipes/ipkg/ipkg-native.inc new file mode 100644 index 0000000000..b52b7b5e20 --- /dev/null +++ b/recipes/ipkg/ipkg-native.inc @@ -0,0 +1,12 @@ +# NOTE: ipkg now obeys ${libdir}, so ipkg-native now installs +# things into the wrong location inside of offline_root. Backup +# the target libdir and use that. +target_libdir := "${libdir}" + +inherit native + +EXTRA_OECONF += "--with-ipkgdir=${target_libdir}/ipkg" + +DEPENDS = "libtool-native automake-native" +FILESDIR = "${@os.path.dirname(bb.data.getVar('FILE',d,1))}/ipkg-${PV}" +PROVIDES = "" diff --git a/recipes/ipkg/ipkg-native_0.99.163.bb b/recipes/ipkg/ipkg-native_0.99.163.bb new file mode 100644 index 0000000000..dd9ff16b65 --- /dev/null +++ b/recipes/ipkg/ipkg-native_0.99.163.bb @@ -0,0 +1,16 @@ +S = "${WORKDIR}/ipkg-${PV}" + +#require ipkg_${PV}.bb +require ipkg-native.inc +PR = "r6" + +inherit autotools pkgconfig native + +SRC_URI = "http://www.handhelds.org/pub/packages/ipkg/ipkg-${PV}.tar.gz \ + file://update_version_comparision.patch;patch=1 \ + file://enable_debversion.patch;patch=1 \ + file://is-processing.patch;patch=1 \ + file://1-pkg-parse--Optimize-inefficient-parsing.patch;patch=1 \ + file://2-pkg-vec--Optimize-gross-inefficiency.patch;patch=1 \ + " + diff --git a/recipes/ipkg/ipkg.inc b/recipes/ipkg/ipkg.inc new file mode 100644 index 0000000000..ee5da71c22 --- /dev/null +++ b/recipes/ipkg/ipkg.inc @@ -0,0 +1,59 @@ +DESCRIPTION = "Itsy Package Manager" +DESCRIPTION_libipkg = "Itsy Package Manager Library" +SECTION = "base" +LICENSE = "GPL" +PROVIDES = "virtual/ipkg libipkg" + +PACKAGES =+ "libipkg-dev libipkg" +FILES_libipkg-dev = "${libdir}/*.a ${libdir}/*.la ${libdir}/*.so" +FILES_libipkg = "${libdir}/*.so.*" +AUTO_LIBNAME_PKGS = "libipkg" + +SRC_URI = "${HANDHELDS_CVS};module=familiar/dist/ipkg;tag=${@'V' + bb.data.getVar('PV',d,1).replace('.', '-')} \ + file://update_version_comparision.patch;patch=1 \ + file://enable_debversion.patch;patch=1 \ + file://ipkg-configure \ + file://terse.patch;patch=1" + +S = "${WORKDIR}/ipkg/C" + +inherit autotools pkgconfig update-rc.d + +# Define a variable to allow distros to run configure earlier. +# (for example, to enable loading of ethernet kernel modules before networking starts) +IPKG_INIT_POSITION = "98" +IPKG_INIT_POSITION_slugos = "41" + +INITSCRIPT_NAME = "ipkg-configure" +INITSCRIPT_PARAMS = "start ${IPKG_INIT_POSITION} S ." + + +pkg_postinst_ipkg () { +#!/bin/sh +update-alternatives --install ${bindir}/ipkg ipkg ${bindir}/ipkg-cl 100 +} + +pkg_postrm_ipkg () { +#!/bin/sh +update-alternatives --remove ipkg ${bindir}/ipkg-cl +} + +do_install_append() { + install -d ${D}${sysconfdir}/init.d + install -m 0755 ${WORKDIR}/${INITSCRIPT_NAME} ${D}${sysconfdir}/init.d/ +} + +do_stage() { + oe_libinstall -so libipkg ${STAGING_LIBDIR} + install -d ${STAGING_INCDIR}/replace/ + install -m 0644 replace/replace.h ${STAGING_INCDIR}/replace/ + install -d ${STAGING_INCDIR}/libipkg/ + for f in *.h + do + install -m 0644 $f ${STAGING_INCDIR}/libipkg/ + done +} + +# +# FIXME: Install /etc/ipkg.conf and /etc/ipkg/arch.conf +# diff --git a/recipes/ipkg/ipkg_0.99.163.bb b/recipes/ipkg/ipkg_0.99.163.bb new file mode 100644 index 0000000000..f546f6e6c8 --- /dev/null +++ b/recipes/ipkg/ipkg_0.99.163.bb @@ -0,0 +1,23 @@ +include ipkg.inc +PR = "r8" + +S = "${WORKDIR}/ipkg-${PV}" + +SRC_URI = "http://www.handhelds.org/pub/packages/ipkg/ipkg-${PV}.tar.gz \ + file://ipkg-configure \ + file://terse.patch;patch=1 \ + file://is-processing.patch;patch=1 \ + file://1-pkg-parse--Optimize-inefficient-parsing.patch;patch=1 \ + file://2-pkg-vec--Optimize-gross-inefficiency.patch;patch=1 \ + file://lonk-link-name.patch;patch=1 \ + " + +do_stage() { + oe_libinstall -so libipkg ${STAGING_LIBDIR} + install -d ${STAGING_INCDIR}/libipkg/ + for f in *.h + do + install -m 0644 $f ${STAGING_INCDIR}/libipkg/ + done +} + diff --git a/recipes/ipkg/ipkgorphan_0.0.1.bb b/recipes/ipkg/ipkgorphan_0.0.1.bb new file mode 100644 index 0000000000..686f0eb5ee --- /dev/null +++ b/recipes/ipkg/ipkgorphan_0.0.1.bb @@ -0,0 +1,18 @@ +DESCRIPTION = "ipkg orphan package list" +AUTHOR = "Alessandro Iurlano <alessandro.iurlano@gmail.com>" +HOMEPAGE = "aiurlano.netsons.org" +SECTION = "console/applications" +PRIORITY = "optional" +LICENSE = "GPL" +DEPENDS = "ipkg" +PR = "r1" + +SRC_URI = "svn://svn.projects.openmoko.org/svnroot/ipkgorphan/ipkgorphan/tags;module=${PV};rev=HEAD;proto=svn" +S = "${WORKDIR}/${PV}" + +LDFLAGS += "-lipkg" + +do_install() { + install -m 0755 -d ${D}${bindir} + install -m 0755 ${S}/ipkgorphan ${D}${bindir} +} |