From: J. Ali Harlow Date: Thu, 9 Jul 2009 07:23:50 +0000 (+0100) Subject: Initial checkin X-Git-Tag: 0.1^0 X-Git-Url: http://project.juiblex.co.uk/git/?a=commitdiff_plain;h=caa992b3de28f3591e299fb69126a2939f0c9811;p=plover.git Initial checkin --- caa992b3de28f3591e299fb69126a2939f0c9811 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4eedacf --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +Makefile +Makefile.in +aclocal.m4 +config.* +config/ +autom4te.cache/ +configure +libtool +plover-*.tar.gz +stamp-h1 +.deps/ +.libs/ +*.o +*.lo +*.la +plover/plover.pc +setup/resources.rc +setup/setup diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..8932f06 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=plover setup diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100644 index 0000000..69c3355 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -e +mkdir -p config +autoheader +aclocal +libtoolize +automake --foreign --add-missing +autoconf diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..192455f --- /dev/null +++ b/configure.ac @@ -0,0 +1,87 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_INIT([plover],[0.1],[ali@juiblex.co.uk]) +AC_PREREQ(2.59) +AC_CONFIG_AUX_DIR([config]) +AC_CONFIG_SRCDIR([plover/plover.h]) +AC_CONFIG_HEADER([config.h]) +AC_CONFIG_FILES([Makefile +plover/Makefile +plover/plover.pc +setup/Makefile +setup/resources.rc +]) +AM_INIT_AUTOMAKE(no-define) +case $VERSION in + *.*.*) + AC_SUBST(PLOVER_MAJOR_VERSION,[[`echo $VERSION | sed 's/\..*//'`]]) + AC_SUBST(PLOVER_MINOR_VERSION, + [[`echo $VERSION | sed 's/[^.]*\.\([^.]*\)\..*/\1/'`]]) + AC_SUBST(PLOVER_MICRO_VERSION,[[`echo $VERSION | sed 's/.*\.\([^.]*\)/\1/'`]]) ;; + *.*) + AC_SUBST(PLOVER_MAJOR_VERSION,[[`echo $VERSION | sed 's/\..*//'`]]) + AC_SUBST(PLOVER_MINOR_VERSION, + [[`echo $VERSION | sed 's/[^.]*\.\([^.]*\)/\1/'`]]) + AC_SUBST(PLOVER_MICRO_VERSION,0) + ;; + *) + AC_SUBST(PLOVER_MAJOR_VERSION,0) + AC_SUBST(PLOVER_MINOR_VERSION,0) + AC_SUBST(PLOVER_MICRO_VERSION,0) + ;; +esac + +################################################## +# Checks for programs. +################################################## +AC_PROG_CC +AC_LIBTOOL_WIN32_DLL +AC_PROG_LIBTOOL +PKG_PROG_PKG_CONFIG +AC_CHECK_TOOL(WINDRES,windres,no) +AM_CONDITIONAL([HAVE_WINDRES],[test x$WINDRES != xno]) + +################################################## +# Checks for header files. +################################################## +AC_HEADER_STDC + +################################################## +# Checks for typedefs, structures, and compiler characteristics. +################################################## + +################################################## +# Checks for libraries. +################################################## +PKG_CHECK_MODULES(RAZOR,[razor],[:],[RAZOR_LIBS=-lrazor]) +PKG_CHECK_MODULES(EXPAT,[expat],[:],[EXPAT_LIBS=-lexpat]) +PKG_CHECK_MODULES(ZLIB,[zlib],[:],[ZLIB_LIBS=-lz]) +LIBPLOVER_CFLAGS="$RAZOR_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS" +LIBPLOVER_LIBS="$RAZOR_LIBS $EXPAT_LIBS $ZLIB_LIBS" +AC_SUBST(LIBPLOVER_CFLAGS) +AC_SUBST(LIBPLOVER_LIBS) +save_PKG_CONFIG="$PKG_CONFIG" +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES(SETUP,[whelk]) +PKG_CONFIG="$save_PKG_CONFIG" +save_LIBS="$LIBS" +AC_SEARCH_LIBS([crypt],[crypt]) +SETUP_LIBS="$SETUP_LIBS $RAZOR_LIBS -llua-posix $LIBS" +SETUP_CFLAGS="$SETUP_CFLAGS $RAZOR_CFLAGS" +AC_SUBST(SETUP_LIBS) +AC_SUBST(SETUP_CFLAGS) +LIBS="$save_LIBS" + +################################################## +# Checks for library functions. +################################################## + +################################################## +# Checks for processor independent files. +################################################## + +################################################## +# Generate the various configured files +################################################## +AC_OUTPUT diff --git a/plover/Makefile.am b/plover/Makefile.am new file mode 100644 index 0000000..075dbd8 --- /dev/null +++ b/plover/Makefile.am @@ -0,0 +1,12 @@ +AM_CFLAGS=-g $(LIBPLOVER_CFLAGS) +LIBS=$(LIBPLOVER_LIBS) +INCLUDES=-I$(top_srcdir) +LDFLAGS=-no-undefined + +lib_LTLIBRARIES=libplover.la +libplover_la_SOURCES=plover.h util.c import-yum.c razor.c comps.c + +pkginclude_HEADERS=plover.h + +pkgconfigdir=$(libdir)/pkgconfig +pkgconfig_DATA=plover.pc diff --git a/plover/comps.c b/plover/comps.c new file mode 100644 index 0000000..cdf7b4c --- /dev/null +++ b/plover/comps.c @@ -0,0 +1,437 @@ +/* + * Copyright (C) 2008 Kristian Høgsberg + * Copyright (C) 2008 Red Hat, Inc + * Copyright (C) 2009 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include "plover/plover.h" + +/* Parse a comps.xml package group file. */ + +static struct comps_requirement *comps_package_requirement_new(void) +{ + struct comps_requirement *req; + req=calloc(sizeof(*req),1); + assert(req != NULL); + req->type=COMPS_REQUIREMENT_OPTIONAL; + return req; +} + +static void comps_package_requirement_free_1(struct comps_requirement *req) +{ + if (req) + { + free(req->requires); + free(req->name); + free(req); + } +} + +static void comps_package_requirement_free(struct comps_requirement *req) +{ + struct comps_requirement *next; + while(req) + { + next=req->next; + comps_package_requirement_free_1(req); + req=next; + } +} + +struct comps_group *comps_group_new(void) +{ + struct comps_group *group; + group=calloc(sizeof(*group),1); + assert(group != NULL); + group->bydefault=1; + group->uservisible=1; + return group; +} + +static void comps_group_free_1(struct comps_group *group) +{ + if (group) + { + free(group->id); + free(group->name); + free(group->description); + comps_package_requirement_free(group->packages); + free(group); + } +} +static void comps_group_free(struct comps_group *group) +{ + struct comps_group *next; + while(group) + { + next=group->next; + comps_group_free_1(group); + group=next; + } +} + +struct comps *plover_comps_new(void) +{ + struct comps *comps; + comps=calloc(sizeof(*comps),1); + assert(comps != NULL); + return comps; +} + +void plover_comps_free(struct comps *comps) +{ + if (comps) + { + free(comps->vendor); + comps_group_free(comps->groups); + free(comps); + } +} + +enum comps_state { + COMPS_STATE_BEGIN, + COMPS_STATE_ROOT, + COMPS_STATE_GROUP, + COMPS_STATE_GROUP_ID, + COMPS_STATE_GROUP_NAME, + COMPS_STATE_GROUP_DESCRIPTION, + COMPS_STATE_GROUP_DEFAULT, + COMPS_STATE_GROUP_USERVISIBLE, + COMPS_STATE_GROUP_PACKAGELIST, + COMPS_STATE_GROUP_PACKAGELIST_REQ, +}; + +struct comps_context { + XML_Parser parser; + enum comps_state state; + int unknown_elements; + char *vendor; + struct comps_group *group; + void *p; +}; + +static enum comps_requirement_type comps_to_requirement_type(const char *flags) +{ + if (strcmp(flags, "conditional") == 0) + return COMPS_REQUIREMENT_CONDITIONAL; + else if (strcmp(flags, "mandatory") == 0) + return COMPS_REQUIREMENT_MANDATORY; + else if (strcmp(flags, "default") == 0) + return COMPS_REQUIREMENT_DEFAULT; + else + return COMPS_REQUIREMENT_OPTIONAL; +} + +static void comps_start_element(void *data,const char *name,const char **atts) +{ + struct comps_context *ctx = data; + struct comps_group *group; + struct comps_requirement *packages; + int i; +#if 0 + fprintf(stderr,"Starting element '"); + switch(ctx->state) + { + case COMPS_STATE_BEGIN: + fprintf(stderr,"/"); + break; + case COMPS_STATE_ROOT: + fprintf(stderr,"/comps/"); + break; + case COMPS_STATE_GROUP: + fprintf(stderr,"/comps/group/"); + break; + case COMPS_STATE_GROUP_ID: + fprintf(stderr,"/comps/group/id/"); + break; + case COMPS_STATE_GROUP_NAME: + fprintf(stderr,"/comps/group/name/"); + break; + case COMPS_STATE_GROUP_DESCRIPTION: + fprintf(stderr,"/comps/group/description/"); + break; + case COMPS_STATE_GROUP_DEFAULT: + fprintf(stderr,"/comps/group/default/"); + break; + case COMPS_STATE_GROUP_USERVISIBLE: + fprintf(stderr,"/comps/group/uservisible/"); + break; + case COMPS_STATE_GROUP_PACKAGELIST: + fprintf(stderr,"/comps/group/packagelist/"); + break; + case COMPS_STATE_GROUP_PACKAGELIST_REQ: + fprintf(stderr,"/comps/group/packagelist/packagereq/"); + break; + + } + for(i=0;iunknown_elements;i++) + fprintf(stderr,"*/"); + fprintf(stderr,"%s'\n",name); +#endif + if (ctx->unknown_elements) + ctx->unknown_elements++; + else if (ctx->state==COMPS_STATE_BEGIN && !strcmp(name,"comps")) + { + ctx->state=COMPS_STATE_ROOT; + for (i=0;atts[i];i+=2) + { + if (!strcmp(atts[i], + "http://project.juiblex.co.uk/plover/ns/2009\xFFvendor")) + ctx->vendor=strdup(atts[i+1]); + } + } + else if (ctx->state==COMPS_STATE_ROOT && !strcmp(name,"group")) + { + ctx->state=COMPS_STATE_GROUP; + group=comps_group_new(); + group->next=ctx->group; + ctx->group=group; + } + else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"id")) + { + ctx->state=COMPS_STATE_GROUP_ID; + ctx->p=&ctx->group->id; + } + else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"name")) + { + ctx->state=COMPS_STATE_GROUP_NAME; + ctx->p=&ctx->group->name; + } + else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"description")) + { + ctx->state=COMPS_STATE_GROUP_DESCRIPTION; + ctx->p=&ctx->group->description; + } + else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"default")) + { + ctx->state=COMPS_STATE_GROUP_DEFAULT; + ctx->p=&ctx->group->bydefault; + } + else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"uservisible")) + { + ctx->state=COMPS_STATE_GROUP_USERVISIBLE; + ctx->p=&ctx->group->uservisible; + } + else if (ctx->state==COMPS_STATE_GROUP && !strcmp(name,"packagelist")) + ctx->state=COMPS_STATE_GROUP_PACKAGELIST; + else if (ctx->state==COMPS_STATE_GROUP_PACKAGELIST && + !strcmp(name,"packagereq")) + { + packages=comps_package_requirement_new(); + packages->next=ctx->group->packages; + ctx->group->packages=packages; + for (i=0;atts[i];i+=2) + { + if (!strcmp(atts[i],"type")) + packages->type=comps_to_requirement_type(atts[i+1]); + else if (!strcmp(atts[i],"requires")) + { + packages->requires=strdup(atts[i+1]); + packages->type=COMPS_REQUIREMENT_CONDITIONAL; + } + } + ctx->state=COMPS_STATE_GROUP_PACKAGELIST_REQ; + ctx->p=&packages->name; + } + else + ctx->unknown_elements++; +} + +struct comps_list +{ + struct comps_list *next; + /* body */ +}; + +void *comps_list_reverse(void *list) +{ + struct comps_list *link=list,*prev=NULL,*next; + while(link) + { + next=link->next; + link->next=prev; + prev=link; + link=next; + } + return prev; +} + +static void comps_end_element(void *data,const char *name) +{ + struct comps_context *ctx=data; + if (ctx->unknown_elements) + ctx->unknown_elements--; + else + switch (ctx->state) + { + case COMPS_STATE_ROOT: + ctx->group=comps_list_reverse(ctx->group); + ctx->state=COMPS_STATE_BEGIN; + break; + case COMPS_STATE_GROUP: + ctx->group->packages=comps_list_reverse(ctx->group->packages); + ctx->state=COMPS_STATE_ROOT; + break; + case COMPS_STATE_GROUP_ID: + case COMPS_STATE_GROUP_NAME: + case COMPS_STATE_GROUP_DESCRIPTION: + case COMPS_STATE_GROUP_DEFAULT: + case COMPS_STATE_GROUP_USERVISIBLE: + case COMPS_STATE_GROUP_PACKAGELIST: + ctx->state=COMPS_STATE_GROUP; + break; + case COMPS_STATE_GROUP_PACKAGELIST_REQ: + ctx->state=COMPS_STATE_GROUP_PACKAGELIST; + break; + } +#if 0 + fprintf(stderr,"Ending element '"); + switch(ctx->state) + { + case COMPS_STATE_BEGIN: + fprintf(stderr,"/"); + break; + case COMPS_STATE_ROOT: + fprintf(stderr,"/comps/"); + break; + case COMPS_STATE_GROUP: + fprintf(stderr,"/comps/group/"); + break; + case COMPS_STATE_GROUP_ID: + fprintf(stderr,"/comps/group/id/"); + break; + case COMPS_STATE_GROUP_NAME: + fprintf(stderr,"/comps/group/name/"); + break; + case COMPS_STATE_GROUP_DESCRIPTION: + fprintf(stderr,"/comps/group/description/"); + break; + case COMPS_STATE_GROUP_DEFAULT: + fprintf(stderr,"/comps/group/default/"); + break; + case COMPS_STATE_GROUP_USERVISIBLE: + fprintf(stderr,"/comps/group/uservisible/"); + break; + case COMPS_STATE_GROUP_PACKAGELIST: + fprintf(stderr,"/comps/group/packagelist/"); + break; + case COMPS_STATE_GROUP_PACKAGELIST_REQ: + fprintf(stderr,"/comps/group/packagelist/packagereq/"); + break; + + } + { + int i; + for(i=0;iunknown_elements;i++) + fprintf(stderr,"*/"); + } + fprintf(stderr,"%s'\n",name); +#endif +} + +static void comps_character_data(void *data,const XML_Char *s,int len) +{ + struct comps_context *ctx=data; + char *str; + switch (ctx->state) + { + case COMPS_STATE_GROUP_ID: + case COMPS_STATE_GROUP_NAME: + case COMPS_STATE_GROUP_DESCRIPTION: + case COMPS_STATE_GROUP_PACKAGELIST_REQ: + *(char **)ctx->p=str=malloc(len+1); + memcpy(str,s,len); + str[len]='\0'; + break; + case COMPS_STATE_GROUP_DEFAULT: + case COMPS_STATE_GROUP_USERVISIBLE: + *(int *)ctx->p=*s=='T'||*s=='t'; + break; + } +} + +#define XML_BUFFER_SIZE 4096 + +struct comps *plover_comps_new_from_file(const char *filename) +{ + struct comps_context ctx={0}; + void *buf; + int len; + FILE *fp; + XML_ParsingStatus status; + struct comps *comps; + fp=fopen(filename,"r"); + if (!fp) + return NULL; + ctx.state=COMPS_STATE_BEGIN; + ctx.parser=XML_ParserCreateNS(NULL,'\xFF'); + XML_SetUserData(ctx.parser,&ctx); + XML_SetElementHandler(ctx.parser,comps_start_element,comps_end_element); + XML_SetCharacterDataHandler(ctx.parser,comps_character_data); + do + { + XML_GetParsingStatus(ctx.parser,&status); + switch (status.parsing) + { + case XML_SUSPENDED: + XML_ResumeParser(ctx.parser); + break; + case XML_PARSING: + case XML_INITIALIZED: + buf=XML_GetBuffer(ctx.parser,XML_BUFFER_SIZE); + len=fread(buf,1,XML_BUFFER_SIZE,fp); + if (len<0) + { + comps_group_free(ctx.group); + XML_ParserFree(ctx.parser); + fclose(fp); + return NULL; + } + if (!XML_ParseBuffer(ctx.parser,len,!len)) + { + comps_group_free(ctx.group); + XML_ParserFree(ctx.parser); + fclose(fp); + return NULL; + } + break; + case XML_FINISHED: + break; + } + } while (status.parsing!=XML_FINISHED); + XML_ParserFree(ctx.parser); + fclose(fp); + comps=plover_comps_new(); + comps->vendor=ctx.vendor; + comps->groups=ctx.group; + return comps; +} + +struct comps_group *plover_comps_lookup_group(struct comps *comps, + const char *id) +{ + struct comps_group *group; + for(group=comps->groups;group;group=group->next) + if (!strcmp(group->id,id)) + return group; + return NULL; +} diff --git a/plover/import-yum.c b/plover/import-yum.c new file mode 100644 index 0000000..d6c0c5e --- /dev/null +++ b/plover/import-yum.c @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2008 Kristian Høgsberg + * Copyright (C) 2008 Red Hat, Inc + * Copyright (C) 2009 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "plover.h" + +/* Import a yum filelist as a razor package set. */ + +enum { + YUM_STATE_BEGIN, + YUM_STATE_PACKAGE_NAME, + YUM_STATE_PACKAGE_ARCH, + YUM_STATE_SUMMARY, + YUM_STATE_DESCRIPTION, + YUM_STATE_URL, + YUM_STATE_LICENSE, + YUM_STATE_CHECKSUM, + YUM_STATE_REQUIRES, + YUM_STATE_PROVIDES, + YUM_STATE_OBSOLETES, + YUM_STATE_CONFLICTS, + YUM_STATE_FILE +}; + +struct yum_context { + XML_Parser primary_parser; + XML_Parser filelists_parser; + XML_Parser current_parser; + + struct razor_importer *importer; + struct import_property_context *current_property_context; + char name[256], arch[64], summary[512], description[4096]; + char url[256], license[64], buffer[512], *p; + char pkgid[128]; + uint32_t property_type; + int state; + + int total, current; +}; + +static uint32_t +yum_to_razor_relation (const char *flags) +{ + if (flags[0] == 'L') { + if (flags[1] == 'T') + return RAZOR_PROPERTY_LESS; + else + return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL; + } else if (flags[0] == 'G') { + if (flags[1] == 'T') + return RAZOR_PROPERTY_GREATER; + else + return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL; + } else + return RAZOR_PROPERTY_EQUAL; +} + +static void +yum_primary_start_element(void *data, const char *name, const char **atts) +{ + struct yum_context *ctx = data; + const char *n, *epoch, *version, *release; + char buffer[128]; + uint32_t pre, relation, flags; + int i; + + if (strcmp(name, "metadata") == 0) { + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "packages") == 0) + ctx->total = atoi(atts[i + 1]); + } + } else if (strcmp(name, "name") == 0) { + ctx->state = YUM_STATE_PACKAGE_NAME; + ctx->p = ctx->name; + } else if (strcmp(name, "arch") == 0) { + ctx->state = YUM_STATE_PACKAGE_ARCH; + ctx->p = ctx->arch; + } else if (strcmp(name, "version") == 0) { + epoch = NULL; + version = NULL; + release = NULL; + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "epoch") == 0) + epoch = atts[i + 1]; + else if (strcmp(atts[i], "ver") == 0) + version = atts[i + 1]; + else if (strcmp(atts[i], "rel") == 0) + release = atts[i + 1]; + } + if (version == NULL || release == NULL) { + fprintf(stderr, "invalid version tag, " + "missing version or release attribute\n"); + return; + } + + razor_build_evr(buffer, sizeof buffer, epoch, version, release); + razor_importer_begin_package(ctx->importer, + ctx->name, buffer, ctx->arch); + } else if (strcmp(name, "summary") == 0) { + ctx->p = ctx->summary; + ctx->state = YUM_STATE_SUMMARY; + } else if (strcmp(name, "description") == 0) { + ctx->p = ctx->description; + ctx->state = YUM_STATE_DESCRIPTION; + } else if (strcmp(name, "url") == 0) { + ctx->p = ctx->url; + ctx->state = YUM_STATE_URL; + } else if (strcmp(name, "checksum") == 0) { + ctx->p = ctx->pkgid; + ctx->state = YUM_STATE_CHECKSUM; + } else if (strcmp(name, "rpm:license") == 0) { + ctx->p = ctx->license; + ctx->state = YUM_STATE_LICENSE; + } else if (strcmp(name, "rpm:requires") == 0) { + ctx->state = YUM_STATE_REQUIRES; + ctx->property_type = RAZOR_PROPERTY_REQUIRES; + } else if (strcmp(name, "rpm:provides") == 0) { + ctx->state = YUM_STATE_PROVIDES; + ctx->property_type = RAZOR_PROPERTY_PROVIDES; + } else if (strcmp(name, "rpm:obsoletes") == 0) { + ctx->state = YUM_STATE_OBSOLETES; + ctx->property_type = RAZOR_PROPERTY_OBSOLETES; + } else if (strcmp(name, "rpm:conflicts") == 0) { + ctx->state = YUM_STATE_CONFLICTS; + ctx->property_type = RAZOR_PROPERTY_CONFLICTS; + } else if (strcmp(name, "rpm:entry") == 0 && + ctx->state != YUM_STATE_BEGIN) { + n = NULL; + epoch = NULL; + version = NULL; + release = NULL; + relation = RAZOR_PROPERTY_EQUAL; + pre = 0; + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "name") == 0) + n = atts[i + 1]; + else if (strcmp(atts[i], "epoch") == 0) + epoch = atts[i + 1]; + else if (strcmp(atts[i], "ver") == 0) + version = atts[i + 1]; + else if (strcmp(atts[i], "rel") == 0) + release = atts[i + 1]; + else if (strcmp(atts[i], "flags") == 0) + relation = yum_to_razor_relation(atts[i + 1]); + else if (strcmp(atts[i], "pre") == 0) + pre = + RAZOR_PROPERTY_PRE | + RAZOR_PROPERTY_POST | + RAZOR_PROPERTY_PREUN | + RAZOR_PROPERTY_POSTUN; + } + + if (n == NULL) { + fprintf(stderr, "invalid rpm:entry, " + "missing name or version attributes\n"); + return; + } + + razor_build_evr(buffer, sizeof buffer, epoch, version, release); + flags = ctx->property_type | relation | pre; + razor_importer_add_property(ctx->importer, n, flags, buffer); + } +} + +static void +yum_primary_end_element (void *data, const char *name) +{ + struct yum_context *ctx = data; + + switch (ctx->state) { + case YUM_STATE_PACKAGE_NAME: + case YUM_STATE_PACKAGE_ARCH: + case YUM_STATE_SUMMARY: + case YUM_STATE_DESCRIPTION: + case YUM_STATE_URL: + case YUM_STATE_LICENSE: + case YUM_STATE_CHECKSUM: + case YUM_STATE_FILE: + ctx->state = YUM_STATE_BEGIN; + break; + } + + if (strcmp(name, "package") == 0) { + razor_importer_add_details(ctx->importer, ctx->summary, + ctx->description, ctx->url, + ctx->license); + + XML_StopParser(ctx->current_parser, XML_TRUE); + ctx->current_parser = ctx->filelists_parser; + + printf("\rimporting %d/%d", ++ctx->current, ctx->total); + fflush(stdout); + } +} + +static void +yum_character_data (void *data, const XML_Char *s, int len) +{ + struct yum_context *ctx = data; + + switch (ctx->state) { + case YUM_STATE_PACKAGE_NAME: + case YUM_STATE_PACKAGE_ARCH: + case YUM_STATE_SUMMARY: + case YUM_STATE_DESCRIPTION: + case YUM_STATE_URL: + case YUM_STATE_LICENSE: + case YUM_STATE_CHECKSUM: + case YUM_STATE_FILE: + memcpy(ctx->p, s, len); + ctx->p += len; + *ctx->p = '\0'; + break; + } +} + +static void +yum_filelists_start_element(void *data, const char *name, const char **atts) +{ + struct yum_context *ctx = data; + const char *pkg, *pkgid; + int i; + + if (strcmp(name, "package") == 0) { + pkg = NULL; + pkgid = NULL; + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "name") == 0) + pkg = atts[i + 1]; + else if (strcmp(atts[i], "pkgid") == 0) + pkgid = atts[i + 1]; + } + if (strcmp(pkgid, ctx->pkgid) != 0) + fprintf(stderr, "primary.xml and filelists.xml " + "mismatch for %s: %s vs %s", + pkg, pkgid, ctx->pkgid); + } else if (strcmp(name, "file") == 0) { + ctx->state = YUM_STATE_FILE; + ctx->p = ctx->buffer; + } +} + +static void +yum_filelists_end_element (void *data, const char *name) +{ + struct yum_context *ctx = data; + + ctx->state = YUM_STATE_BEGIN; + if (strcmp(name, "package") == 0) { + XML_StopParser(ctx->current_parser, XML_TRUE); + ctx->current_parser = ctx->primary_parser; + razor_importer_finish_package(ctx->importer); + } else if (strcmp(name, "file") == 0) + razor_importer_add_file(ctx->importer, ctx->buffer); + +} + +#define XML_BUFFER_SIZE 4096 + +struct razor_set * +plover_razor_set_create_from_yum(const char *base) +{ + struct yum_context ctx; + void *buf; + int len, ret; + gzFile primary, filelists; + XML_ParsingStatus status; + + ctx.importer = razor_importer_create(); + ctx.state = YUM_STATE_BEGIN; + + ctx.primary_parser = XML_ParserCreate(NULL); + XML_SetUserData(ctx.primary_parser, &ctx); + XML_SetElementHandler(ctx.primary_parser, + yum_primary_start_element, + yum_primary_end_element); + XML_SetCharacterDataHandler(ctx.primary_parser, + yum_character_data); + + ctx.filelists_parser = XML_ParserCreate(NULL); + XML_SetUserData(ctx.filelists_parser, &ctx); + XML_SetElementHandler(ctx.filelists_parser, + yum_filelists_start_element, + yum_filelists_end_element); + XML_SetCharacterDataHandler(ctx.filelists_parser, + yum_character_data); + + primary = gzopen("primary.xml.gz", "rb"); + if (primary == NULL) + return NULL; + filelists = gzopen("filelists.xml.gz", "rb"); + if (filelists == NULL) + return NULL; + + ctx.current_parser = ctx.primary_parser; + + ctx.current = 0; + + do { + XML_GetParsingStatus(ctx.current_parser, &status); + switch (status.parsing) { + case XML_SUSPENDED: + ret = XML_ResumeParser(ctx.current_parser); + break; + case XML_PARSING: + case XML_INITIALIZED: + buf = XML_GetBuffer(ctx.current_parser, + XML_BUFFER_SIZE); + if (ctx.current_parser == ctx.primary_parser) + len = gzread(primary, buf, XML_BUFFER_SIZE); + else + len = gzread(filelists, buf, XML_BUFFER_SIZE); + if (len < 0) { + fprintf(stderr, + "couldn't read input: %s\n", + strerror(errno)); + return NULL; + } + + XML_ParseBuffer(ctx.current_parser, len, len == 0); + break; + case XML_FINISHED: + break; + } + } while (status.parsing != XML_FINISHED); + + + XML_ParserFree(ctx.primary_parser); + XML_ParserFree(ctx.filelists_parser); + + gzclose(primary); + gzclose(filelists); + + printf ("\nsaving\n"); + return razor_importer_finish(ctx.importer); +} diff --git a/plover/plover.h b/plover/plover.h new file mode 100644 index 0000000..97d0eeb --- /dev/null +++ b/plover/plover.h @@ -0,0 +1,54 @@ +#ifndef __PLOVER_H__ +#define __PLOVER_H__ + +#include + +enum comps_requirement_type +{ + COMPS_REQUIREMENT_OPTIONAL, + COMPS_REQUIREMENT_DEFAULT, + COMPS_REQUIREMENT_MANDATORY, + COMPS_REQUIREMENT_CONDITIONAL +}; + +struct comps_requirement +{ + struct comps_requirement *next; + enum comps_requirement_type type; + char *requires; /* For type == COMPS_REQUIREMENT_CONDITIONAL */ + char *name; +}; + +struct comps_group +{ + struct comps_group *next; + char *id,*name,*description; + int bydefault,uservisible; + struct comps_requirement *packages; +}; + +struct comps +{ + char *vendor; + struct comps_group *groups; +}; + +char *plover_strconcat(const char *string,...); + +struct razor_set *plover_razor_set_create_from_yum(const char *base); + +struct razor_set *plover_relocate_packages(struct razor_set *set, + const char *base,struct razor_relocations *relocations); +int plover_run_transaction(struct razor_transaction *trans,const char *base, + const char *install_root,struct razor_set *system,struct razor_set *next, + struct razor_relocations *relocations); +int plover_install(const char *base,const char *prefix,char **pkgs); +int plover_remove(char **pkgs); + +struct comps *plover_comps_new(void); +struct comps *plover_comps_new_from_file(const char *filename); +void plover_comps_free(struct comps *comps); +struct comps_group *plover_comps_lookup_group(struct comps *comps, + const char *id); + +#endif /* __PLOVER_H__ */ diff --git a/plover/plover.pc.in b/plover/plover.pc.in new file mode 100644 index 0000000..bab71c3 --- /dev/null +++ b/plover/plover.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: plover +Description: Plover packaging system +Version: @VERSION@ +Requires: razor expat zlib +Libs: -L${libdir} -lplover +Cflags: -I${includedir} diff --git a/plover/razor.c b/plover/razor.c new file mode 100644 index 0000000..e849a87 --- /dev/null +++ b/plover/razor.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2008 Kristian Høgsberg + * Copyright (C) 2008 Red Hat, Inc + * Copyright (C) 2009 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "plover/plover.h" + +static char *rpm_filename(const char *name,const char *version,const char *arch) +{ + const char *v; + v=strchr(version,':'); /* Skip epoch */ + if (v) + v++; + else + v=version; + return plover_strconcat(name,"-",v,".",arch,".rpm",NULL); +} + +struct razor_set *plover_relocate_packages(struct razor_set *set, + const char *base,struct razor_relocations *relocations) +{ + struct razor_importer *importer; + struct razor_property_iterator *prop_iter; + struct razor_package_iterator *pkg_iter; + struct razor_file_iterator *file_iter; + struct razor_package *package; + struct razor_property *property; + struct razor_rpm *rpm; + const char *name,*version,*arch,*summary,*desc,*url,*license; + char *s,*file; + uint32_t flags; + importer=razor_importer_create(); + pkg_iter=razor_package_iterator_create(set); + while (razor_package_iterator_next(pkg_iter,&package,RAZOR_DETAIL_NAME, + &name,RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch, + RAZOR_DETAIL_SUMMARY,&summary,RAZOR_DETAIL_DESCRIPTION,&desc, + RAZOR_DETAIL_URL,&url,RAZOR_DETAIL_LICENSE,&license,RAZOR_DETAIL_LAST)) + { + s=rpm_filename(name,version,arch); + file=plover_strconcat(base,"/rpms/",s,NULL); + free(s); + rpm=razor_rpm_open(file); + if (!rpm) + { + fprintf(stderr,"failed to open rpm %s\n",file); + razor_package_iterator_destroy(pkg_iter); + razor_importer_destroy(importer); + free(file); + return NULL; + } + free(file); + razor_relocations_set_rpm(relocations,rpm); + razor_rpm_close(rpm); + razor_importer_begin_package(importer,name,version,arch); + razor_importer_add_details(importer,summary,desc,url,license); + prop_iter=razor_property_iterator_create(set,package); + while (razor_property_iterator_next(prop_iter,&property,&name,&flags, + &version)) + razor_importer_add_property(importer,name,flags,version); + razor_property_iterator_destroy(prop_iter); + file_iter=razor_file_iterator_create(set,package,0); + while (razor_file_iterator_next(file_iter,&name)) + { + name=razor_relocations_apply(relocations,name); + razor_importer_add_file(importer,name); + } + razor_file_iterator_destroy(file_iter); + razor_importer_finish_package(importer); + } + razor_package_iterator_destroy(pkg_iter); + return razor_importer_finish(importer); +} + +int plover_run_transaction(struct razor_transaction *trans,const char *base, + const char *install_root,struct razor_set *system,struct razor_set *next, + struct razor_relocations *relocations) +{ + struct razor_install_iterator *ii; + struct razor_package *package; + struct razor_set *set; + enum razor_install_action action; + struct razor_rpm *rpm; + const char *name,*version,*arch; + char *s,*file; + int count; + ii=razor_set_create_install_iterator(system,next); + printf("Running Transaction\n"); + while (razor_install_iterator_next(ii,&set,&package,&action,&count)) + { + if (action==RAZOR_INSTALL_ACTION_REMOVE) + { + razor_package_get_details(set,package,RAZOR_DETAIL_NAME,&name, + RAZOR_DETAIL_LAST); + printf(" Removing : %s ",name); + if (razor_package_remove(set,package,install_root,0)<0) + printf( + "\nWarning: one or more errors occurred while removing %s", + name); + printf("\n"); + } + else + { + razor_package_get_details(set,package,RAZOR_DETAIL_NAME,&name, + RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch, + RAZOR_DETAIL_LAST); + printf(" Installing : %s ",name); + s=rpm_filename(name,version,arch); + file=plover_strconcat(base,"/rpms/",s,NULL); + free(s); + rpm=razor_rpm_open(file); + if (!rpm) + { + fprintf(stderr,"failed to open rpm %s\n",file); + free(file); + razor_install_iterator_destroy(ii); + return -1; + } + if (relocations) + razor_rpm_set_relocations(rpm,relocations); + razor_transaction_fixup_package(trans,package,rpm); + if (razor_rpm_install(rpm,install_root,1)<0) + { + fprintf(stderr,"failed to install rpm %s\n",file); + razor_rpm_close(rpm); + free(file); + razor_install_iterator_destroy(ii); + return -1; + } + razor_rpm_close(rpm); + free(file); + printf("\n"); + } + } + razor_install_iterator_destroy(ii); + return 0; +} + +static int plover_mark_package_for_update(struct razor_transaction *trans, + struct razor_set *set,const char *pkg) +{ + struct razor_package_iterator *pi; + struct razor_package *package; + const char *name; + int retval=-1; + pi=razor_package_iterator_create(set); + while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name, + RAZOR_DETAIL_LAST)) + { + if (!strcmp(name,pkg)) + { + razor_transaction_update_package(trans,package); + retval=0; + break; + } + } + razor_package_iterator_destroy(pi); + return retval; +} + +int plover_install(const char *base,const char *prefix,char **pkgs) +{ + int i; + char *s; + char *install_root; + struct razor_root *root; + struct razor_set *system,*set,*upstream,*next; + struct razor_transaction *trans; + struct razor_relocations *relocations; + install_root=getenv("RAZOR_ROOT"); + if (!install_root) + install_root=""; + if (prefix) + { + relocations=razor_relocations_create(); + razor_relocations_add(relocations,"/usr",prefix); + } + /* + * Calling razor_root_open() on a system that hasn't yet had + * razor_root_create() run generates a confusing error message + * on stderr. Avoid this by trying to open it R/O first which + * fails without generating any error. + */ + set=razor_root_open_read_only(install_root); + if (set) + razor_set_destroy(set); + else + razor_root_create(install_root); + root=razor_root_open(install_root); + if (!root) + return -1; + system=razor_root_get_system_set(root); + if (!system) + { + razor_root_close(root); + return -1; + } + s=plover_strconcat(base,"/repodata",NULL); + if (!s) + { + razor_root_close(root); + return -1; + } + if (chdir(s)<0) + { + perror(s); + free(s); + razor_root_close(root); + return -1; + } + free(s); + set=plover_razor_set_create_from_yum(base); + if (!set) + { + razor_root_close(root); + return -1; + } + upstream=plover_relocate_packages(set,base,relocations); + razor_set_destroy(set); + trans=razor_transaction_create(system,upstream); + for(i=0;pkgs[i];i++) + if (plover_mark_package_for_update(trans,upstream,pkgs[i])) + { + fprintf(stderr,"%s: Package not found\n",pkgs[i]); + razor_root_close(root); + return -1; + } + razor_transaction_resolve(trans); + if (razor_transaction_describe(trans)>0) + { + razor_root_close(root); + return -1; + } + next=razor_transaction_commit(trans); + plover_run_transaction(trans,base,install_root,system,next,relocations); + razor_root_update(root,next); + razor_transaction_destroy(trans); + razor_set_destroy(next); + razor_set_destroy(upstream); + if (prefix) + razor_relocations_destroy(relocations); + return razor_root_commit(root); +} + +static int plover_mark_packages_for_removal(struct razor_transaction *trans, + struct razor_set *set,const char *pkg) +{ + struct razor_package_iterator *pi; + struct razor_package *package; + const char *name; + int retval=pkg?-1:0; + pi=razor_package_iterator_create(set); + while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_NAME,&name, + RAZOR_DETAIL_LAST)) + { + if (!pkg || !strcmp(name,pkg)) + { + razor_transaction_remove_package(trans,package); + retval=0; + } + } + razor_package_iterator_destroy(pi); + return retval; +} + +int plover_remove(char **pkgs) +{ + int i; + char *install_root; + struct razor_root *root; + struct razor_set *system,*set,*upstream,*next; + struct razor_transaction *trans; + install_root=getenv("RAZOR_ROOT"); + if (!install_root) + install_root=""; + set=razor_root_open_read_only(install_root); + if (!set) + return 0; + razor_set_destroy(set); + root=razor_root_open(install_root); + if (!root) + return -1; + system=razor_root_get_system_set(root); + if (!system) + { + razor_root_close(root); + return -1; + } + upstream=razor_set_create_without_root(); + trans=razor_transaction_create(system,upstream); + if (pkgs) + for(i=0;pkgs[i];i++) + { + if (plover_mark_packages_for_removal(trans,system,pkgs[i])) + { + fprintf(stderr,"%s: Package not found\n",pkgs[i]); + razor_transaction_destroy(trans); + razor_set_destroy(upstream); + razor_set_destroy(system); + razor_root_close(root); + return -1; + } + } + else + plover_mark_packages_for_removal(trans,system,NULL); + razor_transaction_resolve(trans); + if (razor_transaction_describe(trans)>0) + { + razor_transaction_destroy(trans); + razor_set_destroy(upstream); + razor_set_destroy(system); + razor_root_close(root); + return -1; + } + next=razor_transaction_commit(trans); + plover_run_transaction(trans,NULL,install_root,system,next,NULL); + razor_root_update(root,next); + razor_transaction_destroy(trans); + razor_set_destroy(next); + razor_set_destroy(upstream); + return razor_root_commit(root); +} diff --git a/plover/util.c b/plover/util.c new file mode 100644 index 0000000..df4d3f9 --- /dev/null +++ b/plover/util.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include "config.h" +#include "plover.h" + +char *plover_strconcat(const char *string,...) +{ + va_list ap,aq; + size_t n; + char *result=NULL,*t; + const char *s; + if (string) + { + va_start(ap,string); + va_copy(aq,ap); + n=strlen(string); + while((s=va_arg(aq,const char *))) + n+=strlen(s); + va_end(aq); + result=malloc(n+1); + if (result) + { + strcpy(result,string); + t=result+strlen(result); + while((s=va_arg(ap,const char *))) + { + strcpy(t,s); + t+=strlen(t); + } + } + va_end(ap); + } + return result; +} diff --git a/setup/Makefile.am b/setup/Makefile.am new file mode 100644 index 0000000..78c729a --- /dev/null +++ b/setup/Makefile.am @@ -0,0 +1,22 @@ +AM_CFLAGS=-g $(SETUP_CFLAGS) +LDADD=../plover/libplover.la $(SETUP_LIBS) +INCLUDES=-I$(top_srcdir) + +bin_PROGRAMS=setup + +setup_SOURCES=setup.c +setup_LDFLAGS=-all-static +if HAVE_WINDRES +setup_SOURCES+=resources.rc +endif + +.png.pnm: + pngtopnm $< | pnmquant 256 > $@ + +resources.$(OBJEXT): resources.rc setup.ico + $(WINDRES) resources.rc $@ + +setup.ico: icon16.pnm icon22.pnm icon32.pnm + ppmtowinicon -output=$@ $^ + +EXTRA_DIST=icon16.png icon22.png icon32.png diff --git a/setup/icon16.png b/setup/icon16.png new file mode 100644 index 0000000..0ca1590 Binary files /dev/null and b/setup/icon16.png differ diff --git a/setup/icon22.png b/setup/icon22.png new file mode 100644 index 0000000..4b7f82c Binary files /dev/null and b/setup/icon22.png differ diff --git a/setup/icon32.png b/setup/icon32.png new file mode 100644 index 0000000..361cd51 Binary files /dev/null and b/setup/icon32.png differ diff --git a/setup/resources.rc.in b/setup/resources.rc.in new file mode 100644 index 0000000..51a31cf --- /dev/null +++ b/setup/resources.rc.in @@ -0,0 +1,32 @@ +#include + +MAINICON ICON "setup.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_VERS +ION@,0 + PRODUCTVERSION @PLOVER_MAJOR_VERSION@,@PLOVER_MINOR_VERSION@,@PLOVER_MICRO_V +ERSION@,0 + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + { + BLOCK "StringFileInfo" + { + BLOCK "080904B0" + { + VALUE "CompanyName","The plover development team" + VALUE "FileDescription","Plover setup program" + VALUE "FileVersion","@PACKAGE_VERSION@" + VALUE "InternalName","setup" + VALUE "LegalCopyright", + "Copyright (c) 2009 J. Ali Harlow et al" + VALUE "OriginalFilename","setup.exe" + VALUE "ProductName","plover" + VALUE "ProductVersion","@PACKAGE_VERSION@" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation",0x809,0x4B0 + } + } diff --git a/setup/setup.c b/setup/setup.c new file mode 100644 index 0000000..9bfbda1 --- /dev/null +++ b/setup/setup.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2009 J. Ali Harlow + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#ifdef WIN32 +#include +#include +#endif +#include +#include "config.h" +#include "plover/plover.h" +#include "whelk/whelk.h" + +LUALIB_API int luaopen_posix(lua_State *L); + +struct vector { + int len,alloc; + char **strings; +}; + +struct vector *vector_new(void) +{ + struct vector *vector; + vector=malloc(sizeof(*vector)); + vector->len=0; + vector->alloc=16; + vector->strings=calloc(vector->alloc,sizeof(char *)); + return vector; +} + +void vector_append(struct vector *vector,const char *str) +{ + if (++(vector->len)>=vector->alloc) + { + vector->alloc*=2; + vector->strings=realloc(vector->strings,vector->alloc*sizeof(char *)); + } + vector->strings[vector->len-1]=strdup(str); + vector->strings[vector->len]=NULL; +} + +int vector_contains(struct vector *vector,const char *str) +{ + int i; + for(i=0;ilen;i++) + if (!strcmp(vector->strings[i],str)) + return 1; + return 0; +} + +void vector_free(struct vector *vector) +{ + int i; + for(i=0;ilen;i++) + free(vector->strings[i]); + free(vector->strings); + free(vector); +} + +static void *alloc_lua(void *user_data,void *ptr,size_t osize,size_t nsize) +{ + if (!nsize) + { + free(ptr); + return NULL; + } + else + return realloc(ptr,nsize); +} + +void setup() +{ + char path[PATH_MAX],*s,*t,*prefix; + int changed; + struct comps *comps; + struct comps_group *group; + struct comps_requirement *pkg; + struct vector *packages=NULL; +#ifdef WIN32 + SHGetFolderPath(NULL,CSIDL_PROGRAM_FILES|CSIDL_FLAG_DONT_VERIFY,NULL,0, + path); + prefix=strdup(path); + GetModuleFileName(NULL,path,sizeof(path)); + s=strrchr(path,'/'); + if (s) + { + t=strrchr(s,'\\'); + if (t) + s=t; + } + else + s=strrchr(path,'\\'); + if (s) + *s='\0'; +#else + strcpy(path,"/tmp"); + prefix=NULL; +#endif + s=plover_strconcat(path,"/repodata/comps.xml",NULL); + comps=plover_comps_new_from_file(s); + if (!comps) + { + perror(s); + exit(1); + } + free(s); +#ifdef WIN32 + s=plover_strconcat(prefix,"\\",comps->vendor?comps->vendor:"Plover",NULL); + free(prefix); + prefix=s; +#endif + group=plover_comps_lookup_group(comps,"base"); + if (!group) + { + fprintf(stderr,"No base group found in comps.xml\n"); + exit(1); + } + packages=vector_new(); + do + { + changed=0; + for(pkg=group->packages;pkg;pkg=pkg->next) + { + if (vector_contains(packages,pkg->name)) + continue; + if (pkg->type==COMPS_REQUIREMENT_DEFAULT || + pkg->type==COMPS_REQUIREMENT_MANDATORY || + pkg->type==COMPS_REQUIREMENT_CONDITIONAL && + vector_contains(packages,pkg->requires)) + { + changed++; + vector_append(packages,pkg->name); + } + } + } while(changed); + if (!packages->len) + { + fprintf(stderr,"No packages to install\n"); + exit(1); + } + plover_install(path,prefix,packages->strings); + vector_free(packages); + plover_comps_free(comps); +#ifdef WIN32 + free(prefix); +#endif +} + +int main(int argc,char **argv) +{ + razor_set_lua_loader("posix",luaopen_posix); + razor_set_lua_loader("whelk",luaopen_whelk); + if (argc>1 && !strcmp(argv[1],"-u")) + plover_remove(NULL); + else + setup(); +}