Commit 2f83991c authored by Bernhard Link's avatar Bernhard Link

miscellaneous things to implement integrated update

parent 04e14c15
......@@ -209,12 +209,20 @@ retvalue chunk_getvalue(const char *chunk,const char *name,char **value) {
return RET_NOTHING;
b = field;
/* jump over spaces at the beginning */
if( isspace(*b) )
b++;
/* search for the end */
e = b;
while( *e != '\n' && *e != '\0' )
e++;
val = strndup(b,e-b);
/* remove trailing spaced */
while( e > b && *e && isspace(*e) )
e--;
if( e != b )
val = strndup(b,e-b+1);
else
val = strdup("");
if( !val )
return RET_ERROR_OOM;
*value = val;
......
......@@ -29,28 +29,13 @@ struct download {
FILE *pipe;
};
retvalue download_initialize(struct download **download,const char *config) {
const char *m,*me,*nl;
char *method;
retvalue download_initialize(struct download **download,const char *method,const char *config) {
FILE *pipe;
struct download *d;
fprintf(stderr,"download_initialize: '%s'\n",config);
m = config;
while( *m && isblank(*m) )
m++;
nl = m;
while( *nl && *nl != '\n' )
nl++;
me = nl;
while( me > m && isblank(*me) )
me--;
if( me == m || !(method = strndup(m,me-m+1)) )
return RET_ERROR_OOM;
fprintf(stderr,"download_initialize: '%s' '%s'\n",method,config);
d = malloc(sizeof(struct download));
if( !d ) {
free(method);
return RET_ERROR_OOM;
}
......@@ -58,15 +43,13 @@ retvalue download_initialize(struct download **download,const char *config) {
if( !pipe ) {
fprintf(stderr,"Error executing '%s': %m\n",method);
free(d);
free(method);
return RET_ERRNO(errno);
}
fprintf(stderr,"Executed '%s': %m\n",method);
free(method);
if( *nl ) {
nl++;
fwrite(nl,strlen(nl),1,pipe);
if( *config ) {
fputs(config,pipe);
fputc('\n',pipe);
}
d->pipe = pipe;
*download = d;
......
......@@ -9,7 +9,7 @@
struct download;
retvalue download_initialize(struct download **download,const char *config);
retvalue download_initialize(struct download **download,const char *method,const char *config);
retvalue download_add(struct download *download,const char *orig,const char *dest);
retvalue download_run(struct download *download);
retvalue download_cancel(struct download *download);
......
......@@ -35,6 +35,7 @@
#include "sources.h"
#include "release.h"
#include "download.h"
#include "updates.h"
#ifndef STD_BASE_DIR
#define STD_BASE_DIR "/var/spool/mirrorer"
......@@ -922,7 +923,7 @@ static retvalue exportsource(void *data,const char *component) {
if( !dbname ) {
return RET_ERROR_OOM;
}
filename = mprintf("%s/%s/sources/Sources.gz",d->dirofdist,component);
filename = mprintf("%s/%s/source/Sources.gz",d->dirofdist,component);
if( !filename ) {
free(dbname);
return RET_ERROR_OOM;
......@@ -980,81 +981,56 @@ int export(int argc,char *argv[]) {
/***********************update********************************/
static retvalue fetchupstreamcomponentlists(
struct download *download,
const char *chunk,
const struct release *release,
const char *upstream,
const char *origin,
const char *destination) {
const char *toget,*saveas;
toget = mprintf("dists/%s/source/Sources.gz",origin);
saveas = mprintf("%s_%s_%s_Sources.gz",release->codename,upstream,origin);
fprintf(stderr,"... '%s':'%s'>'%s'\n",upstream,origin,destination);
download_add(download,toget,saveas);
return RET_NOTHING;
}
static retvalue fetchupstreamlists(const char *chunk,const struct release *release,const char *upstream) {
static retvalue fetchupstreamlists(void *data,const char *chunk,const struct release *release,struct update *update) {
retvalue result,r;
char *keyname,*component,*destination,*origin;
char *config;
struct strlist components;
int i;
char *from,*method;
int i,j;
struct download *download;
/* * Check which components to update * */
keyname = mprintf("Update-%s",upstream);
if( !keyname )
r = RET_ERROR_OOM;
else
r = chunk_getwordlist(chunk,keyname,&components);
if( !RET_IS_OK(r) ) {
if( r== RET_NOTHING ) {
fprintf(stderr,"Cannot find '%s' line in '%s' specification.\n",keyname,release->codename);
return RET_ERROR;
} else
return r;
}
char *toget,*saveas;
const char *origin,*dest,*arch;
/* * Prepare the download-backend * */
r = chunk_getextralines(chunk,keyname,&config);
/* it was already found, so should be found again */
assert( r != RET_NOTHING );
r = chunk_getvalue(chunk,"From",&from);
if( !RET_IS_OK(r) )
return r;
r = chunk_getvalue(chunk,"Method",&method);
if( !RET_IS_OK(r) )
return r;
r = download_initialize(&download,config);
r = download_initialize(&download,method,from);
if( !RET_IS_OK(r) )
return r;
//TODO: implement error-checking...
toget = mprintf("dists/%s/Release",update->suite_from);
saveas = mprintf("%s/%s_%s_Release",listdir,release->codename,update->name);
download_add(download,toget,saveas);
free(toget);free(saveas);
/* * Iterator over components to update * */
result = RET_NOTHING;
for( i = 0 ; i < components.count ; i++ ) {
component = components.values[i];
if( !(destination = strchr(component,'>')) || !*(destination+1))
r = fetchupstreamcomponentlists(download,
chunk,release,upstream,
component,component);
else {
origin = strndup(component,destination-component);
destination++;
if( !origin )
r = RET_ERROR_OOM;
else
r = fetchupstreamcomponentlists(download,
chunk,release,upstream,
origin,destination);
free(origin);
}
for( i = 0 ; i < update->components_from.count ; i++ ) {
origin = update->components_from.values[i];
dest = update->components_into.values[i];
RET_UPDATE(result,r);
toget = mprintf("dists/%s/%s/source/Sources.gz",update->suite_from,origin);
saveas = mprintf("%s/%s_%s_%s_Sources.gz",listdir,release->codename,update->name,origin);
download_add(download,toget,saveas);
free(toget);free(saveas);
for( j = 0 ; j < update->architectures.count ; j++ ) {
arch =update->architectures.values[j];
toget = mprintf("dists/%s/%s/binary-%s/Packages.gz",update->suite_from,origin,arch);
saveas = mprintf("%s/%s_%s_%s_%s_Packages.gz",listdir,release->codename,update->name,origin,arch);
download_add(download,toget,saveas);
free(toget);free(saveas);
}
}
strlist_free(&components);
/* * fire up downloading * */
......@@ -1070,39 +1046,6 @@ static retvalue fetchupstreamlists(const char *chunk,const struct release *relea
return result;
}
static retvalue doupdate(void *dummy,const char *chunk,const struct release *release) {
retvalue result,r;
char *upstream;
struct strlist upstreams;
int i;
r = chunk_getwordlist(chunk,"Update",&upstreams);
if( r == RET_NOTHING && verbose > 1 ) {
fprintf(stderr,"Ignoring release '%s', as it describes no update\n",release->codename);
}
if( !RET_IS_OK(r) )
return r;
result = RET_NOTHING;
/* Iteratate over all given upstreams */
for( i = 0 ; i < upstreams.count ; i++ ) {
upstream = upstreams.values[i];
if( verbose > 0 ) {
fprintf(stderr,"Updating '%s':'%s'...\n",release->codename,upstream);
}
r = fetchupstreamlists(chunk,release,upstream);
RET_UPDATE(result,r);
if( RET_WAS_ERROR(r) )
break;
}
strlist_free(&upstreams);
return result;
}
int update(int argc,char *argv[]) {
retvalue result;
......@@ -1111,7 +1054,7 @@ int update(int argc,char *argv[]) {
return 1;
}
result = release_foreach(confdir,argc-1,argv+1,doupdate,NULL,force);
result = updates_foreach(confdir,argc-1,argv+1,fetchupstreamlists,NULL,force);
return EXIT_RET(result);
}
......
......@@ -117,8 +117,8 @@ void release_free(struct release *release) {
free(release->origin);
free(release->label);
free(release->description);
free(release->architectures);
free(release->components);
strlist_free(&release->architectures);
strlist_free(&release->components);
free(release);
}
}
......@@ -133,30 +133,26 @@ retvalue release_parse(struct release **release,const char *chunk) {
if( !r )
return RET_ERROR_OOM;
#define parse(name,target) ret = chunk_getvalue(chunk,name,&target); \
if(!RET_IS_OK(ret)) { \
#define checkret if(!RET_IS_OK(ret)) { \
release_free(r); \
return ret; \
}
#define parseold(name,target) f = chunk_getfield(name,chunk); \
if( !f ) { \
*release = NULL; \
release_free(r); \
return RET_NOTHING; \
} \
target = chunk_dupvalue(f); \
if( !target ) { \
release_free(r); \
return RET_ERROR_OOM; \
}
parse("Codename",r->codename);
parse("Suite",r->suite);
parse("Version",r->version);
parse("Origin",r->origin);
parse("Label",r->label);
parse("Description",r->description);
parse("Architectures",r->architectures);
parse("Components",r->components);
ret = chunk_getvalue(chunk,"Codename",&r->codename);
checkret;
ret = chunk_getvalue(chunk,"Suite",&r->suite);
checkret;
ret = chunk_getvalue(chunk,"Version",&r->version);
checkret;
ret = chunk_getvalue(chunk,"Origin",&r->origin);
checkret;
ret = chunk_getvalue(chunk,"Label",&r->label);
checkret;
ret = chunk_getvalue(chunk,"Description",&r->description);
checkret;
ret = chunk_getwordlist(chunk,"Architectures",&r->architectures);
checkret;
ret = chunk_getwordlist(chunk,"Components",&r->components);
checkret;
*release = r;
return RET_OK;
......@@ -298,50 +294,27 @@ static retvalue printmd5andsize(FILE *f,const char *dir,const char *fmt,...) {
return RET_OK;
}
static char *first_word(const char *c) {
const char *p;
p = c;
while( *p && !isspace(*p) ) {
p++;
}
return strndup(c,p-c);
}
static const char *next_word(const char *c) {
while( *c && !isspace(*c) )
c++;
while( *c && isspace(*c) )
c++;
return c;
}
/* call <sourceaction> for each source part of <release> and <binaction> for each binary part of it. */
retvalue release_foreach_part(const struct release *release,release_each_source_action sourceaction,release_each_binary_action binaction,void *data) {
retvalue result,r;
int i,j;
const char *arch,*comp;
char *a,*c;
result = RET_NOTHING;
for( comp=release->components ; *comp ; comp=next_word(comp) ) {
c = first_word(comp);
if( !c ) {return RET_ERROR_OOM;}
for( arch=release->architectures ; *arch ; arch=next_word(arch) ) {
a = first_word(arch);
if( !a ) {free(c);return RET_ERROR_OOM;}
if( strcmp(a,"source") != 0 ) {
r = binaction(data,c,a);
for( i = 0 ; i < release->components.count ; i++ ) {
comp = release->components.values[i];
for( j = 0 ; j < release->architectures.count ; j++ ) {
arch = release->architectures.values[j];
if( strcmp(arch,"source") != 0 ) {
r = binaction(data,comp,arch);
RET_UPDATE(result,r);
//TODO: decide if break on error/introduce a force-flag
}
free(a);
}
r = sourceaction(data,c);
r = sourceaction(data,comp);
RET_UPDATE(result,r);
//TODO: dito
free(c);
}
return result;
}
......@@ -431,13 +404,14 @@ retvalue release_gen(const struct release *release,const char *distdir) {
"Codename: %s\n"
"Version: %s\n"
"Date: %s\n"
"Architectures: %s\n"
"Components: %s\n"
"Description: %s\n"
"MD5Sums:\n",
"Architectures: ",
release->origin, release->label, release->suite,
release->codename, release->version, buffer,
release->architectures, release->components,
release->codename, release->version, buffer);
strlist_fprint(f,&release->architectures);
fprintf(f, "\nComponents: ");
strlist_fprint(f,&release->components);
fprintf(f, "\nDescription: %s\n"
"MD5Sums:\n",
release->description);
/* generate bin/source-Release-files and add md5sums */
......
......@@ -5,6 +5,7 @@
#include "error.h"
#warning "What's hapening here?"
#endif
#include "strlist.h"
/* check for a <filetocheck> to be have same md5sum and size as <nametocheck> in <releasefile>,
* returns 1 if ok, == 0 if <nametocheck> not specified, != 1 on error */
......@@ -13,7 +14,7 @@ retvalue release_checkfile(const char *releasefile,const char *nametocheck,const
struct release {
char *codename,*suite,*version;
char *origin,*label,*description;
char *architectures,*components;
struct strlist architectures,components;
};
void release_free(struct release *release);
......
......@@ -19,6 +19,8 @@
#include <errno.h>
#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include "error.h"
#include "strlist.h"
......@@ -67,7 +69,7 @@ void strlist_free(struct strlist *strlist) {
retvalue strlist_add(struct strlist *strlist, char *element) {
char **v;
assert(strlist != NULL);
assert(strlist != NULL && element != NULL);
if( strlist->count >= strlist->size ) {
strlist->size += 8;
......@@ -82,3 +84,40 @@ retvalue strlist_add(struct strlist *strlist, char *element) {
strlist->values[strlist->count++] = element;
return RET_OK;
}
retvalue strlist_fprint(FILE *file,const struct strlist *strlist) {
int c;
char **p;
assert(strlist != NULL);
assert(file != NULL);
c = strlist->count;
p = strlist->values;
while( c > 0 ) {
fputs(*(p++),file);
if( --c > 0 ) {
fputc(' ',file);
}
}
return RET_OK;
}
/* duplicate with content */
retvalue strlist_dup(struct strlist *dest,const struct strlist *orig) {
int i;
assert(dest != NULL && orig != NULL);
dest->size = dest->count = orig->count;
dest->values = calloc(dest->count,sizeof(char*));;
if( !dest->values )
return RET_ERROR_OOM;
for( i = 0 ; i < dest->count ; i++ ) {
if( !(dest->values[i] = strdup(orig->values[i])) ) {
strlist_free(dest);
return RET_ERROR_OOM;
}
}
return RET_OK;
}
......@@ -17,6 +17,12 @@ void strlist_free(struct strlist *strlist);
/* add a string, will get property of the strlist and free'd by it */
retvalue strlist_add(struct strlist *strlist,char *element);
/* print a space seperated list of elements */
retvalue strlist_fprint(FILE *file,const struct strlist *strlist);
/* duplicate with content */
retvalue strlist_dup(struct strlist *dest,const struct strlist *orig);
int strlist_in(const struct strlist *strlist,const char *element);
#endif
......@@ -37,21 +37,29 @@
extern int verbose;
// typedef retvalue updatesaction(void *data,const char *chunk,const struct release *release,const char *name);
// typedef retvalue updatesaction(void *data,const char *chunk,const struct release *release,struct update *update);
struct mydata {
const char *updatesfile;
int force;
struct strlist upstreams;
const struct release *release;
const struct strlist *updates;
void *data;
updatesaction *action;
void *data;
};
static retvalue processupdates(void *data,const char *chunk) {
struct mydata *d = data;
retvalue r;
char *name;
int i;
struct update update;
struct strlist componentlist;
const struct strlist *components;
int components_need_free;
const char *component;
char *origin,*destination;
r = chunk_getvalue(chunk,"Name",&name);
r = chunk_getvalue(chunk,"Name",&update.name);
if( r == RET_NOTHING ) {
fprintf(stderr,"Unexpected chunk in updates-file: '%s'.\n",chunk);
return r;
......@@ -59,42 +67,127 @@ static retvalue processupdates(void *data,const char *chunk) {
if( !RET_IS_OK(r) )
return r;
if( strlist_in(d->updates,name) ) {
r = RET_NOTHING;
if( strlist_in(&d->upstreams,update.name) ) {
if( verbose > 2 ) {
fprintf(stderr,"processing '%s' for '%s'\n",name,d->release->codename);
fprintf(stderr,"processing '%s' for '%s'\n",update.name,d->release->codename);
}
/* * Check which suite to update from * */
r = chunk_getvalue(chunk,"Suite",&update.suite_from);
if( r == RET_NOTHING ) {
/* if nothing given, try the one we know */
update.suite_from = strdup(d->release->codename);
if( !update.suite_from )
r = RET_ERROR_OOM;
} // TODO: check for some token to be repaced by the codename?
// i.e. */updates gets stable/updates unstable/updates ...
if( !RET_WAS_ERROR(r) ) {
/* * Check which architectures to update from * */
r = chunk_getwordlist(chunk,"Architectures",&update.architectures);
if( r == RET_NOTHING ) {
/* if nothing given, try to get all the distribution knows */
r = strlist_dup(&update.architectures,&d->release->architectures);
}
if( !RET_WAS_ERROR(r) ) {
/* * Check which components to update from * */
components_need_free = 1;
components = &componentlist;
r = chunk_getwordlist(chunk,"Components",&componentlist);
if( r == RET_NOTHING ) {
/* if nothing given, try to get all the distribution knows */
components = &d->release->components;
components_need_free = 0;
}
// TODO: generate more information...
// (like which distributions, architectures and components to update)
d->action(d->data,chunk,d->release,name);
if( !RET_WAS_ERROR(r) ) {
strlist_new(&update.components_from);
strlist_new(&update.components_into);
free(name);
return RET_OK;
/* * Iterator over components to update * */
r = RET_NOTHING;
for( i = 0 ; i < components->count ; i++ ) {
component = components->values[i];
if( !(destination = strchr(component,'>')) || !*(destination+1)) {
destination = strdup(component);
origin = strdup(component);
} else {
origin = strndup(component,destination-component);
destination = strdup(destination+1);
}
if( !origin || ! destination ) {
r = RET_ERROR_OOM;
break;
}
//TODO: check if in release.compoents
r = strlist_add(&update.components_from,origin);
if( RET_WAS_ERROR(r) )
break;
r = strlist_add(&update.components_into,destination);
if( RET_WAS_ERROR(r) )
break;
}
if( !RET_WAS_ERROR(r) )
r = d->action(d->data,chunk,d->release,&update);
strlist_free(&update.components_from);
strlist_free(&update.components_into);
if( components_need_free )
strlist_free(&componentlist);
}
strlist_free(&update.architectures);
}
free(update.suite_from);
}
} else if( verbose > 5 ) {
fprintf(stderr,"skipping '%s' in this run\n",name);
fprintf(stderr,"skipping '%s' in this run\n",update.name);
}
free(name);
return RET_NOTHING;
free(update.name);
return r;
}
retvalue updates_foreach_matching(const char *conf,const struct release *release,const struct strlist *updates,updatesaction action,void *data,int force) {
retvalue result;
char *fn;
static retvalue doupdate(void *data,const char *chunk,const struct release *release) {
struct mydata *d = data;
retvalue r;
r = chunk_getwordlist(chunk,"Update",&d->upstreams);
if( r == RET_NOTHING && verbose > 1 ) {
fprintf(stderr,"Ignoring release '%s', as it describes no update\n",release->codename);
}
if( !RET_IS_OK(r) )
return r;
d->release = release;
r = chunk_foreach(d->updatesfile,processupdates,d,d->force);
strlist_free(&d->upstreams);
return r;
}
retvalue updates_foreach(const char *confdir,int argc,char *argv[],updatesaction action,void *data,int force) {
struct mydata mydata;
retvalue result;
mydata.release = release;
mydata.updates = updates;
mydata.data = data;
mydata.action = action;
fn = calc_dirconcat(conf,"updates");
if( !fn )
mydata.updatesfile = calc_dirconcat(confdir,"updates");
if( !mydata.updatesfile )
return RET_ERROR_OOM;
mydata.force=force;
mydata.action=action;
mydata.data=data;
result = chunk_foreach(fn,processupdates,&mydata,force);
result = release_foreach(confdir,argc,argv,doupdate,&mydata,force);
free((char*)mydata.updatesfile);
free(fn);
return result;
}
......@@ -9,10 +9,18 @@
#include "release.h"
#include "strlist.h"
typedef retvalue updatesaction(void *data,const char *chunk,const struct release *release,const char *name);
retvalue updates_foreach_matching(const char *conf,const struct release *release,const struct strlist *updates,updatesaction action,void *data,int force);
struct update {
char *name;
struct strlist architectures;
char *suite_from;
struct strlist components_from;
struct strlist components_into;
};
typedef retvalue updatesaction(void *data,const char *chunk,const struct release *release,struct update *update);
retvalue updates_foreach(const char *confdir,int argc,char *argv[],updatesaction action,void *data,int force);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment