Good morning list. If you have c skills and would like to help out the Gentoo Embedded project then I have a task for you. One of our favorite applications in the embedded world is /bin/busybox. BusyBox needs a few hrs of code loving put into it. Currently BusyBox only supports rpm and deb, so this is the next logical step. The task if you choose to accept it will be to code a very minimal emerge.c busybox applet. The applet will need to meet the following requirements.
1) The ability to fetch a native portage built package .tbz2 2) No changes in package format handling. (ie no .ipk/.apk/.homebrew) 3) The ability to record the contents of a package exactly the same way portage does. (/var/db/pkg/$PN/CONTENTS) 4) The ability to uninstall a binary package based on whats in listed in the CONTENTS file. 5) The ability to omit files from being installed based on a setting called INSTALL_MASK. This should behave exactly like the current portage implementation if the INSTALL_MASK feature which accepts globing. ex: INSTALL_MASK="*.a /usr/lib/*.o /usr/include *.pl" 6) use the bb api as much as you can (ie the socket code etc is mostly already there provided by libbb.a) 7) Not take many weeks/months to do. 8) And mostly importantly have fun doing it. Now I know a few of you on this list have to be c coders so I'm attaching a very basic non working standalone mock up that's 50% c and 50% ash to give you a rough idea of what we are thinking. -- Ned Ludd <[EMAIL PROTECTED]> Gentoo Linux
/*
* Distributed under the terms of the GNU General Public License v2
* $Header: $
*
********************************************************************
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include <assert.h>
#include <zlib.h>
#define ECACHE "/var/db/pkg"
#define file_exists(f) (access(f, R_OK) == 0)
#define dir_exists(f) (access(f, R_OK) == 0)
static int verbose = 0;
static int update = 0;
static int pretend = 0;
static int list = 0;
static char *file_ext = ".tbz2";
char *root;
static char *index_dir = "/dev/shm";
/* write me */
static int fetched_package()
{
return 0;
}
static int mkalldirs()
{
return 0;
}
static char **read_sort()
{
return 0;
}
static const char *rcsid = "$Id: $";
void einfo(char *str)
{
fprintf(stdout, ">>> %s\n", str);
}
void eerror(char *str)
{
fprintf(stderr, "!!! %s\n", str);
}
void die(char *str)
{
eerror(str);
_exit(EXIT_FAILURE);
}
int hasq(char *needle, char *haystack)
{
if (strstr(needle, haystack) == 0)
return 1;
return 0;
}
static void self_setup()
{
#undef FOO
#define FOO "Try adding it to your /etc/make.conf or exporting it as an environment variable."
/* verify envionment variables exist before going on */
if (getenv("PKGDIR") == NULL)
die("PKGDIR is not set. " FOO);
if (getenv("PORTAGE_BINHOST") == NULL)
die("PORTAGE_BINHOST is not set. " FOO);
if (getenv("PORTAGE_TMPDIR") == NULL)
die("PORTAGE_TMPDIR is not set. " FOO);
if (!dir_exists("${PKGDIR}/All"))
mkalldirs("${PKGDIR}/All");
if (!file_exists("${INDEX_DIR}/INDEX"))
update = 1;
#undef FOO
}
void fetch_package(char *pkgname)
{
if (fetched_package(pkgname))
return;
}
void update_index()
{
if (!update)
return;
}
void usage(char **argv)
{
printf("Usage: %s <opts>\n", argv[0]);
puts(" -h|--help : This help");
puts(" -d|--debug : set -x");
puts(" -p|--pretend : pretend only");
puts(" -v|--verbose : set verbose flag");
puts(" -f|--fetch : fetch binary files");
puts(" -K|--usepkgonly : use binary package");
puts(" -C|--unmerge : uninstall a binary package");
puts(" --info|info : display info");
puts(" --sync : preform $opt operation");
puts(" --list : update index and list packages");
puts(" --update : update index file");
puts(" --clean : clean up tmpfiles");
puts(" --root=<dir> : define ROOT=$ROOT");
puts(" --index=<dir> : define INDEX_DIR=$INDEX_DIR");
puts(" --pkgdir=<dir> : define PKGDIR=$PKGDIR");
puts(" --tmpdir=<dir> : define PORTAGE_TMPDIR=$PORTAGE_TMPDIR");
puts(" --binhost=<url> : define PORTAGE_BINHOST=$PORTAGE_BINHOST");
exit(1);
}
static struct option const long_options[] = {
{"help", no_argument, 0, 'h'},
{"debug", no_argument, 0, 'd'},
{"pretend", no_argument, 0, 'p'},
{"verbose", no_argument, 0, 'v'},
{"fetch", no_argument, 0, 'f'},
{"usepkgonly", no_argument, 0, 'K'},
{"unmerge", no_argument, 0, 'C'},
{"root", required_argument, 0, 'r'},
{"query", required_argument, 0, 'q'},
{NULL, no_argument, NULL, 0}
};
void showopt(int c, char *data)
{
int i;
for (i = 0; long_options[i].name; i++) {
if (long_options[i].val == c) {
printf(" -%c|--%s\t: %s\n", c, long_options[i].name, data);
}
}
}
#define PARSE_FLAGS "hvr:q:CKp"
void parseargs(int argc, char *argv[])
{
int flag;
opterr = 0;
while ((flag = (int) getopt_long(argc, argv, PARSE_FLAGS,
long_options, NULL)) != EOF) {
switch (flag) {
case 'C': /* uninstall pkg */
break;
case 'K': /* use bin pkg only */
break;
case 'p': /* pretend */
pretend = 1;
break;
case 'r': /* ROOT= */
root = (char *) strdup(optarg);
break;
case 'v': /* verbose */
verbose++;
break;
case 'q': /* query file */
qfile_main(argv[1]);
break;
case 'h':
showopt('h', "Print this help and exit");
showopt('d', "Enable debugging");
showopt('p', "pretend only");
showopt('v', "set verbose flag");
showopt('f', "fetch binary files");
showopt('K', "install binary package");
showopt('C', "uninstall a binary package");
break;
case 'V':
printf("%s compiled %s\n", __FILE__, __DATE__);
_exit(0);
case '?':
default:
break;
}
}
}
void qfile(const char *path, const char *fname)
{
gzFile *fp;
register DIR *dir;
register struct dirent *dentry;
struct stat st;
static char *p;
int len = 0, flen = strlen(fname);
char buffer[BUFSIZ];
char buf[BUFSIZ];
assert(flen != 0);
if ((chdir(path) == 0) && ((dir = opendir(path)))) {
readdir(dir);
readdir(dir); /* skip . & .. */
while ((dentry = readdir(dir))) {
len = (strlen(path) + 2 + strlen(dentry->d_name) + 9 + 4);
p = malloc(len + 1);
strncpy(p, path, len);
strncat(p, "/", len);
strncat(p, dentry->d_name, len);
strncat(p, "/CONTENTS.gz", len);
if ((stat(p, &st)) == (-1)) {
fprintf(stderr, "stat: failed %s\n", p);
free(p);
closedir(dir);
return;
}
printf("%s\n", p);
if ((fp = gzopen(p, "r")) != NULL) {
memset(buf, 0, sizeof(buf));
while (len = gzread(fp, buf, sizeof(buf))) {
/* parse each '\n' while(ptr = strchr(buf, '\n') != NULL) *p=0; strcpy(buf, p+1);
look at second index. verify file exists or does not.
*/
printf("gzread(%s) = %d\n", buf, len);
}
if (gzclose(fp) != Z_OK)
fprintf(stderr, "gzclose: failed\n");
}
}
free(p);
}
closedir(dir);
return;
}
int qfile_main(const char *fname)
{
register DIR *dir;
register struct dirent *dentry;
static char *p;
int len = 0;
char *path = ECACHE;
if ((chdir(path) == 0) && ((dir = opendir(path)))) {
readdir(dir);
readdir(dir); /* skip . & .. */
while ((dentry = readdir(dir))) {
len = (strlen(path) + 2 + strlen(dentry->d_name));
p = (char *) malloc(len);
snprintf(p, len, "%s/%s", path, dentry->d_name);
qfile(p, fname);
free(p);
}
closedir(dir);
}
return 0;
}
int main(int argc, char **argv)
{
char tar_flags[16] = "x";
char **index_cache = NULL;
if (argc == 1)
usage(argv);
root = "/";
parseargs(argc, argv);
// self_setup();
if (verbose)
strcat(tar_flags, "v");
if ((strcmp("$file_ext", ".tbz2")) == 0)
strcat(tar_flags, "j");
if ((strcmp("$file_ext", ".tbz")) == 0)
strcat(tar_flags, "z");
update_index();
if (file_exists("${INDEX_DIR}/INDEX"))
index_cache = read_sort("${INDEX_DIR}/INDEX");
else
index_cache = NULL;
if (list);
/* for (p = pkg; p->next != NULL; p = p->next)
* printf("%s\n", p->name);
*/
_exit(EXIT_SUCCESS);
}
signature.asc
Description: This is a digitally signed message part
