Commit e072a94d authored by Bernhard Link's avatar Bernhard Link

some Ctrl-C and other signal supporting stuff

parent 509901b3
2006-06-16 Bernhard R. Link <brlink@debian.org>
* manpage mentions includeudeb now. (Thanks to Jordi Mallach for noting)
* changed manpage to make clear options are before the command (dito)
* catch TERM, ABRT, INT and QUIT and do not start any new stuff after
that.
2006-06-12 Bernhard R. Link <brlink@debian.org>
* some prework for predelete action
......
......@@ -285,6 +285,11 @@ inline static retvalue aptmethod_startup(struct aptmethodrun *run,struct aptmeth
return RET_ERRNO(err);
}
if( interupted() ) {
(void)close(stdin[0]);(void)close(stdin[1]);
(void)close(stdout[0]);(void)close(stdout[1]);
return RET_ERROR_INTERUPTED;
}
f = fork();
if( f < 0 ) {
int err = errno;
......@@ -948,6 +953,9 @@ static retvalue senddata(struct aptmethod *method) {
return RET_OK;
}
if( interupted() )
return RET_ERROR_INTERUPTED;
method->alreadywritten = 0;
// TODO: make sure this is already checked for earlier...
assert(strchr(method->nexttosend->uri,'\n')==NULL || strchr(method->nexttosend->filename,'\n') == 0);
......@@ -1074,6 +1082,7 @@ static retvalue readwrite(struct aptmethodrun *run,int *workleft,filesdb filesdb
v = select(maxfd+1,&readfds,&writefds,NULL,NULL);
if( v < 0 ) {
int err = errno;
//TODO: handle (err == EINTR) && interupted() specially
fprintf(stderr,"Select returned error: %d=%m\n",err);
*workleft = -1;
// TODO: what to do here?
......@@ -1118,6 +1127,7 @@ retvalue aptmethod_download(struct aptmethodrun *run,const char *methoddir,files
RET_UPDATE(result,r);
r = readwrite(run,&workleft,filesdb);
RET_UPDATE(result,r);
// TODO: check interupted here...
} while( workleft > 0 );
return result;
......
......@@ -65,6 +65,10 @@ static ssize_t readwait(int fd, void *buf, size_t count) {
s = read(fd,buf,count);
if( s < 0 )
return s;
if( interupted() ) {
errno = EINTR;
return -1;
}
if( (size_t)s > count ) {
errno = EINVAL;
return -1;
......@@ -83,6 +87,8 @@ retvalue ar_open(/*@out@*/struct ar_archive **n, const char *filename) {
char buffer[sizeof(AR_MAGIC)];
ssize_t bytesread;
if( interupted() )
return RET_ERROR_INTERUPTED;
ar = calloc(1,sizeof(struct ar_archive));
if( ar == NULL )
return RET_ERROR_OOM;
......@@ -154,6 +160,9 @@ retvalue ar_nextmember(struct ar_archive *ar,/*@out@*/char **filename) {
}
/* read the next header from the file */
if( interupted() )
return RET_ERROR_INTERUPTED;
bytesread = readwait(ar->fd,&ar->currentheader,sizeof(ar->currentheader));
if( bytesread == 0 )
return RET_NOTHING;
......
......@@ -268,6 +268,9 @@ retvalue ubinaries_doreoverride(const struct alloverrides *ao,const char *packag
struct fieldtoadd *fields;
char *newchunk;
if( interupted() )
return RET_ERROR_INTERUPTED;
o = override_search(ao->udeb, packagename);
if( o == NULL )
return RET_NOTHING;
......@@ -293,6 +296,9 @@ retvalue binaries_retrack(UNUSED(struct target *t),const char *packagename,const
//TODO: elliminate duplicate code!
assert(packagename!=NULL);
if( interupted() )
return RET_ERROR_INTERUPTED;
/* is there a sourcename */
r = chunk_getnameandversion(chunk,"Source",&fsourcename,&sourceversion);
if( RET_WAS_ERROR(r) )
......
......@@ -806,6 +806,9 @@ static retvalue changes_includepkgs(const char *dbdir,references refs,struct dis
e = e->next;
continue;
}
if( interupted() ) {
return RET_ERROR_INTERUPTED;
}
if( e->type == fe_DEB ) {
r = deb_addprepared(e->pkg.deb,dbdir,refs,
e->architecture,"deb",
......@@ -875,6 +878,9 @@ retvalue changes_add(const char *dbdir,trackingdb const tracks,references refs,f
if( !RET_WAS_ERROR(r) )
r = changes_check(changesfilename,changes,forcearchitecture,packagetypeonly);
if( interupted() )
RET_UPDATE(r,RET_ERROR_INTERUPTED);
/* add files in the pool */
//TODO: D_DELETE would fail here, what to do?
if( !RET_WAS_ERROR(r) )
......@@ -908,8 +914,11 @@ retvalue changes_add(const char *dbdir,trackingdb const tracks,references refs,f
trackingdata_done(&trackingdata);
return RET_ERROR_OOM;
}
if( interupted() )
r = RET_ERROR_INTERUPTED;
else
/* always D_COPY, and only delete it afterwards... */
r = files_include(filesdb,changesfilename,
r = files_include(filesdb,changesfilename,
changes->changesfilekey,
NULL,NULL,D_COPY);
if( RET_WAS_ERROR(r) ) {
......@@ -925,12 +934,12 @@ retvalue changes_add(const char *dbdir,trackingdb const tracks,references refs,f
distribution,changes,dereferencedfilekeys,
(tracks!=NULL)?&trackingdata:NULL);
if( RET_WAS_ERROR(r) ) {
if( RET_WAS_ERROR(result) ) {
if( tracks != NULL ) {
trackingdata_done(&trackingdata);
}
changes_free(changes);
return r;
return result;
}
if( tracks != NULL ) {
......
......@@ -438,7 +438,7 @@ retvalue deb_addprepared(const struct debpackage *pkg, const char *dbdir,referen
retvalue r,result;
int i;
/* finaly put it into one or more architectures of the distribution */
/* finally put it into one or more architectures of the distribution */
result = RET_NOTHING;
......@@ -447,7 +447,10 @@ retvalue deb_addprepared(const struct debpackage *pkg, const char *dbdir,referen
r = target_initpackagesdb(t,dbdir);
if( !RET_WAS_ERROR(r) ) {
retvalue r2;
r = target_addpackage(t,refs,pkg->package,pkg->version,pkg->control,&pkg->filekeys,FALSE,dereferencedfilekeys,trackingdata,ft_ARCH_BINARY);
if( interupted() )
r = RET_ERROR_INTERUPTED;
else
r = target_addpackage(t,refs,pkg->package,pkg->version,pkg->control,&pkg->filekeys,FALSE,dereferencedfilekeys,trackingdata,ft_ARCH_BINARY);
r2 = target_closepackagesdb(t);
RET_ENDUPDATE(r,r2);
}
......@@ -457,7 +460,10 @@ retvalue deb_addprepared(const struct debpackage *pkg, const char *dbdir,referen
r = target_initpackagesdb(t,dbdir);
if( !RET_WAS_ERROR(r) ) {
retvalue r2;
r = target_addpackage(t,refs,pkg->package,pkg->version,pkg->control,&pkg->filekeys,FALSE,dereferencedfilekeys,trackingdata,ft_ALL_BINARY);
if( interupted() )
r = RET_ERROR_INTERUPTED;
else
r = target_addpackage(t,refs,pkg->package,pkg->version,pkg->control,&pkg->filekeys,FALSE,dereferencedfilekeys,trackingdata,ft_ALL_BINARY);
r2 = target_closepackagesdb(t);
RET_ENDUPDATE(r,r2);
}
......@@ -470,7 +476,10 @@ retvalue deb_addprepared(const struct debpackage *pkg, const char *dbdir,referen
r = target_initpackagesdb(t,dbdir);
if( !RET_WAS_ERROR(r) ) {
retvalue r2;
r = target_addpackage(t,refs,pkg->package,pkg->version,pkg->control,&pkg->filekeys,FALSE,dereferencedfilekeys,trackingdata,ft_ALL_BINARY);
if( interupted() )
r = RET_ERROR_INTERUPTED;
else
r = target_addpackage(t,refs,pkg->package,pkg->version,pkg->control,&pkg->filekeys,FALSE,dereferencedfilekeys,trackingdata,ft_ALL_BINARY);
r2 = target_closepackagesdb(t);
RET_ENDUPDATE(r,r2);
}
......@@ -478,8 +487,6 @@ retvalue deb_addprepared(const struct debpackage *pkg, const char *dbdir,referen
}
RET_UPDATE(distribution->status, result);
// deb_free(pkg);
return result;
}
......
......@@ -439,7 +439,10 @@ retvalue dsc_addprepared(const struct dscpackage *pkg,const char *dbdir,referenc
r = target_initpackagesdb(t,dbdir);
if( !RET_WAS_ERROR(r) ) {
retvalue r2;
r = target_addpackage(t,refs,pkg->package,pkg->version,pkg->control,&pkg->filekeys,FALSE,dereferencedfilekeys,trackingdata,ft_SOURCE);
if( interupted() )
r = RET_ERROR_INTERUPTED;
else
r = target_addpackage(t,refs,pkg->package,pkg->version,pkg->control,&pkg->filekeys,FALSE,dereferencedfilekeys,trackingdata,ft_SOURCE);
r2 = target_closepackagesdb(t);
RET_ENDUPDATE(r,r2);
}
......@@ -467,6 +470,11 @@ retvalue dsc_add(const char *dbdir,references refs,filesdb filesdb,const char *f
if( RET_WAS_ERROR(r) )
return r;
if( interupted() ) {
dsc_free(pkg);
return RET_ERROR_INTERUPTED;
}
if( tracks != NULL ) {
r = trackingdata_summon(tracks,pkg->package,pkg->version,&trackingdata);
if( RET_WAS_ERROR(r) ) {
......
......@@ -33,7 +33,7 @@ extern int verbose;
// of only \n terminated oned. Though this has still to be tested properly...
/* Call action for each chunk in <filename> */
retvalue chunk_foreach(const char *filename,chunkaction action,void *data,int force,bool_t stopwhenok){
retvalue chunk_foreach(const char *filename,chunkaction action,void *data,bool_t stopwhenok){
gzFile f;
retvalue result,ret;
char *chunk;
......@@ -45,20 +45,24 @@ retvalue chunk_foreach(const char *filename,chunkaction action,void *data,int fo
}
result = RET_NOTHING;
while( (ret = chunk_read(f,&chunk)) == RET_OK ) {
if( interupted() ) {
RET_UPDATE(result,RET_ERROR_INTERUPTED);
break;
}
ret = action(data,chunk);
// in this one a segfault was reported, where did
// it come from?
free(chunk);
if( RET_WAS_ERROR(ret) && force <= 0 ) {
if( RET_WAS_ERROR(ret) ) {
if( verbose > 0 )
fprintf(stderr,"Stop reading further chunks from '%s' due to privious errors.\n",filename);
fprintf(stderr,"Stop reading further chunks from '%s' due to previous errors.\n",filename);
break;
}
RET_UPDATE(result,ret);
if( stopwhenok && RET_IS_OK(ret) )
break;
RET_UPDATE(result,ret);
}
RET_UPDATE(result,ret);
//TODO: check result:
......
......@@ -35,7 +35,7 @@ typedef retvalue chunkaction(/*@temp@*/void *data,/*@temp@*/const char *chunk);
/* Call action for each chunk in <filename>,
* until error when not <force> or until ok when <stopwhenok> */
retvalue chunk_foreach(const char *filename,chunkaction action,/*@null@*/ /*@temp@*/void *data,int force,bool_t stopwhenok);
retvalue chunk_foreach(const char *filename,chunkaction action,/*@null@*/ /*@temp@*/void *data,bool_t stopwhenok);
/* modifications of a chunk: */
struct fieldtoadd {
......
......@@ -52,7 +52,8 @@ static retvalue read_control_file(char **control, const char *debfile, struct ar
}
buffer = malloc(size+2);
len = 0;
while( (got = archive_read_data(tar, buffer+len, ((size_t)size+1)-len)) > 0 ) {
while( (got = archive_read_data(tar, buffer+len, ((size_t)size+1)-len)) > 0
&& !interupted() ) {
len += got;
if( len > size ) {
fprintf(stderr, "Internal Error: libarchive miscalculated length of the control file within '%s',\n"
......@@ -61,6 +62,15 @@ static retvalue read_control_file(char **control, const char *debfile, struct ar
return RET_ERROR;
}
}
if( interupted() ) {
free(buffer);
return RET_ERROR_INTERUPTED;
}
if( got < 0 ) {
free(buffer);
fprintf(stderr, "Error reading control file from %s\n", debfile);
return RET_ERROR;
}
if( len < size )
fprintf(stderr, "Warning: libarchive overcalculated length of the control file within '%s',\n"
" perhaps the file is corrupt, perhaps libarchive!\n", debfile);
......@@ -136,6 +146,8 @@ static retvalue read_control_tar(char **control, const char *debfile, struct ar_
e, archive_error_string(tar));
return (e!=0)?(RET_ERRNO(e)):RET_ERROR;
}
if( interupted() )
return RET_ERROR_INTERUPTED;
} else {
r = read_control_file(control, debfile, tar, entry);
if( r != RET_NOTHING )
......@@ -264,6 +276,10 @@ static retvalue read_data_tar(/*@out@*/char **list, const char *debfile, struct
memcpy(filelist + len, name, n_len+1);
len += n_len+1;
}
if( interupted() ) {
free(filelist);
return RET_ERROR_INTERUPTED;
}
a = archive_read_data_skip(tar);
if( a != ARCHIVE_OK ) {
int e = archive_errno(tar);
......
......@@ -70,6 +70,9 @@ retvalue dirs_make_parent(const char *filename) {
retvalue dirs_make_recursive(const char *directory) {
retvalue r,result;
if( interupted() ) {
return RET_ERROR_INTERUPTED;
}
r = dirs_make_parent(directory);
result = dirs_check(directory);
RET_UPDATE(result,r);
......
......@@ -428,7 +428,7 @@ retvalue distribution_getmatched(const char *conf,int argc,const char *argv[],st
return RET_ERROR_MISSING;
}
result = chunk_foreach(fn,adddistribution,&mydata,0,FALSE);
result = chunk_foreach(fn,adddistribution,&mydata,FALSE);
if( !RET_WAS_ERROR(result) ) {
int i;
......@@ -576,7 +576,7 @@ retvalue distribution_exportandfreelist(enum exportwhen when,
d = distributions;
distributions = d->next;
if( RET_WAS_ERROR(d->status) && when != EXPORT_FORCE ) {
if( (RET_WAS_ERROR(d->status)||interupted()) && when != EXPORT_FORCE ) {
if( verbose >= 10 )
fprintf(stderr,
" Not exporting %s because there have been errors and no --export=force.\n",
......@@ -627,7 +627,7 @@ retvalue distribution_export(enum exportwhen when, struct distribution *distribu
"Make sure to run a full export soon.\n", distribution->codename);
return RET_NOTHING;
}
if( when != EXPORT_FORCE && RET_WAS_ERROR(distribution->status) ) {
if( when != EXPORT_FORCE && (RET_WAS_ERROR(distribution->status)||interupted()) ) {
if( verbose >= 10 )
fprintf(stderr,
"Not exporting %s because there have been errors and no --export=force.\n"
......
......@@ -1067,6 +1067,27 @@ does not know anything needing them right know, you can use
To delete them:
.br
\fBreprepro deleteunreferenced\fP
.SH INTERUPTING
Interupting reprepro has its problems.
Some things (like speaking with apt methods, database stuff) can cause
problems when interupted at the wrong time.
Then there are design problems of the code making it hard to destinguish
if the current state is dangerous or non-dangerous to interupt.
Thus if reprepro receives a signal normaly sent to tell a process to
terminate itself softly,
it continues its operation, but does not start any new operations.
(I.e. it will not tell the apt-methods any new file to download, it will
not replace a package in a target, unless it already had started with it,
it will not delete any files gotten dereferenced, and so on).
\fBIt only catches the first signal of each type. The second signal of a
given type will terminate reprepro. You will risk database corruption
and have to remove the lockfile manually.\fP
Also note that even normal interuption leads to code-paths mostly untested
and thus expose a multitude of bugs including those leading to data corruption.
Better think a second more before issuing a command than risking the need
for interuption.
.SH "REPORTING BUGS"
Report bugs or wishlist requests to <brlink@debian.org>
.br
......
......@@ -75,6 +75,8 @@ retvalue donefile_create(const char *filename, const char *expected) {
size_t len;
ssize_t written;
int fd;
if( interupted() )
return RET_ERROR_INTERUPTED;
char *donefilename = calc_addsuffix(filename,"done");
if( donefilename == NULL )
......
......@@ -5,6 +5,8 @@
#include "globals.h"
#endif
bool_t interupted(void);
/* retvalue is simply an int.
* just named to show it follows the given semantics */
typedef int retvalue;
......@@ -18,6 +20,7 @@ typedef int retvalue;
#define RET_ERROR_GPGME (retvalue)-5
#define RET_ERROR_BADSIG (retvalue)-6
#define RET_ERROR_MISSING (retvalue)-7
#define RET_ERROR_INTERUPTED (retvalue)-8
#define RET_IS_OK(r) ((r) == RET_OK)
#define RET_WAS_NO_ERROR(r) ((r) >= (retvalue)0)
......
......@@ -215,6 +215,8 @@ retvalue files_deleteandremove(filesdb filesdb,const char *filekey,bool_t rmdirs
char *filename;
retvalue r;
if( interupted() )
return RET_ERROR_INTERUPTED;
if( verbose >= 0 )
printf("deleting and forgetting %s\n",filekey);
filename = calc_fullfilename(filesdb->mirrordir,filekey);
......
......@@ -25,6 +25,7 @@
#include <strings.h>
#include <malloc.h>
#include <fcntl.h>
#include <signal.h>
#include "error.h"
#define DEFINE_IGNORE_VARIABLES
#include "ignore.h"
......@@ -1817,14 +1818,14 @@ static retvalue callaction(const struct action *action,int argc,const char *argv
}
assert( result != RET_NOTHING );
if( RET_IS_OK(result) ) {
if( RET_IS_OK(result) && !interupted() ) {
result = action->start(references,filesdb,
deletederef?&dereferencedfilekeys:NULL,
argc,argv);
if( deletederef ) {
if( dereferencedfilekeys.count > 0 ) {
if( RET_IS_OK(result) ) {
if( RET_IS_OK(result) && !interupted() ) {
retvalue r;
assert(filesdb!=NULL);
......@@ -2125,6 +2126,24 @@ static void handle_option(int c,const char *optarg) {
}
}
static volatile bool_t was_interupted = FALSE;
static bool_t interuption_printed = FALSE;
bool_t interupted(void) {
if( was_interupted ) {
if( !interuption_printed ) {
interuption_printed = TRUE;
fprintf(stderr, "\n\nInteruption in progress, interupt again to force-stop it risking database corruption\n\n");
}
return TRUE;
} else
return FALSE;
}
static void interupt_signaled(int signal) /*__attribute__((signal))*/;
static void interupt_signaled(UNUSED(int signal)) {
was_interupted = TRUE;
}
int main(int argc,char *argv[]) {
static struct option longopts[] = {
......@@ -2173,6 +2192,15 @@ int main(int argc,char *argv[]) {
const struct action *a;
retvalue r;
int c;
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_ONESHOT;
sa.sa_handler = interupt_signaled;
(void)sigaction(SIGTERM, &sa, NULL);
(void)sigaction(SIGABRT, &sa, NULL);
(void)sigaction(SIGINT, &sa, NULL);
(void)sigaction(SIGQUIT, &sa, NULL);
programname = argv[0];
......@@ -2180,6 +2208,9 @@ int main(int argc,char *argv[]) {
config_state = CONFIG_OWNER_CMDLINE;
if( interupted() )
exit(EXIT_RET(RET_ERROR_INTERUPTED));
while( (c = getopt_long(argc,argv,"+fVvhb:P:i:A:C:S:T:",longopts,NULL)) != -1 ) {
handle_option(c,optarg);
}
......@@ -2187,6 +2218,8 @@ int main(int argc,char *argv[]) {
fprintf(stderr,"No action given. (see --help for available options and actions)\n");
exit(EXIT_FAILURE);
}
if( interupted() )
exit(EXIT_RET(RET_ERROR_INTERUPTED));
/* only for this CONFIG_OWNER_ENVIRONMENT is a bit stupid,
* but perhaps it gets more... */
......@@ -2233,6 +2266,8 @@ int main(int argc,char *argv[]) {
(void)fputs("Out of Memory!\n",stderr);
exit(EXIT_FAILURE);
}
if( interupted() )
exit(EXIT_RET(RET_ERROR_INTERUPTED));
a = all_actions;
while( a->name != NULL ) {
if( strcasecmp(a->name,argv[optind]) == 0 ) {
......
......@@ -241,7 +241,7 @@ retvalue pull_getrules(const char *confdir,struct pull_rule **rules) {
return RET_ERROR_OOM;
data.rules = &pull;
data.confdir = confdir;
r = chunk_foreach(pullfile,pull_parsechunk,&data,0,FALSE);
r = chunk_foreach(pullfile,pull_parsechunk,&data,FALSE);
free(pullfile);
if( RET_IS_OK(r) )
*rules = pull;
......@@ -662,7 +662,7 @@ static inline retvalue pull_searchformissing(const char *dbdir,struct pull_targe
r = upgradelist_pull(p->upgradelist,
source->source,
ud_decide_by_rule, source->rule,
force, dbdir);
dbdir);
RET_UPDATE(result,r);
if( RET_WAS_ERROR(r) && force <= 0 )
return result;
......
......@@ -348,6 +348,9 @@ retvalue sources_doreoverride(const struct alloverrides *ao,const char *packagen
struct fieldtoadd *fields;
char *newchunk;
if( interupted() )
return RET_ERROR_INTERUPTED;
o = override_search(ao->dsc, packagename);
if( o == NULL )
return RET_NOTHING;
......@@ -372,6 +375,9 @@ retvalue sources_retrack(struct target *t,const char *sourcename,const char *chu
//TODO: elliminate duplicate code!
assert(sourcename!=NULL);
if( interupted() )
return RET_ERROR_INTERUPTED;
r = chunk_getvalue(chunk,"Version",&sourceversion);
if( r == RET_NOTHING ) {
fprintf(stderr,"Did not find Version in chunk:'%s'\n",chunk);
......
......@@ -555,7 +555,7 @@ retvalue updates_getpatterns(const char *confdir,struct update_pattern **pattern
return RET_ERROR_OOM;
data.patterns = &update;
data.confdir = confdir;
r = chunk_foreach(updatesfile,parsechunk,&data,0,FALSE);
r = chunk_foreach(updatesfile,parsechunk,&data,FALSE);
free(updatesfile);
if( RET_IS_OK(r) )
*patterns = update;
......@@ -1358,8 +1358,7 @@ static inline retvalue searchformissing(const char *dbdir,struct update_target *
r = upgradelist_update(u->upgradelist,
index->origin->download,index->filename,
ud_decide_by_pattern,
(void*)index->origin->pattern,
force);
(void*)index->origin->pattern);
if( RET_WAS_ERROR(r) ) {
u->incomplete = TRUE;
u->ignoredelete = TRUE;
......
......@@ -423,14 +423,14 @@ static retvalue upgradelist_trypackage(void *data,const char *chunk){
return RET_OK;
}
retvalue upgradelist_update(struct upgradelist *upgrade,struct aptmethod *method,const char *filename,upgrade_decide_function *decide,void *decide_data,int force){
retvalue upgradelist_update(struct upgradelist *upgrade,struct aptmethod *method,const char *filename,upgrade_decide_function *decide,void *decide_data){
upgrade->last = NULL;
upgrade->currentaptmethod = method;
upgrade->predecide = decide;
upgrade->predecide_data = decide_data;
return chunk_foreach(filename,upgradelist_trypackage,upgrade,force,FALSE);
return chunk_foreach(filename,upgradelist_trypackage,upgrade,FALSE);
}
static retvalue try(void *data,UNUSED(const char *package),const char *chunk) {
......@@ -438,7 +438,7 @@ static retvalue try(void *data,UNUSED(const char *package),const char *chunk) {
}
retvalue upgradelist_pull(struct upgradelist *upgrade,struct target *source,upgrade_decide_function *predecide,void *decide_data,int force,const char *dbdir) {
retvalue upgradelist_pull(struct upgradelist *upgrade,struct target *source,upgrade_decide_function *predecide,void *decide_data,const char *dbdir) {
retvalue result,r;
upgrade->last = NULL;
......@@ -449,7 +449,7 @@ retvalue upgradelist_pull(struct upgradelist *upgrade,struct target *source,upgr
r = target_initpackagesdb(source,dbdir);
if( RET_WAS_ERROR(r) )
return r;
result = packages_foreach(source->packages,try,upgrade,force);
result = packages_foreach(source->packages,try,upgrade,FALSE);
r = target_closepackagesdb(source);
RET_UPDATE(result,r);
return result;
......@@ -544,18 +544,28 @@ retvalue upgradelist_install(struct upgradelist *upgrade,const char *dbdir,files
if( pkg->version == pkg->new_version && !pkg->deleted ) {
r = files_expectfiles(files,&pkg->new_filekeys,
&pkg->new_md5sums);
if( ! RET_WAS_ERROR(r) )
if( ! RET_WAS_ERROR(r) ) {
/* upgrade (or possibly downgrade) */
// TODO: trackingdata?
r = target_addpackage(upgrade->target,refs,
pkg->name,pkg->new_version,pkg->new_control,
&pkg->new_filekeys,TRUE,dereferencedfilekeys,NULL,0);
if( interupted() )
r = RET_ERROR_INTERUPTED;
else
r = target_addpackage(upgrade->target,
refs, pkg->name,
pkg->new_version,
pkg->new_control,
&pkg->new_filekeys, TRUE,
dereferencedfilekeys, NULL, 0);
}
RET_UPDATE(result,r);
if( RET_WAS_ERROR(r) && force <= 0 )
break;
}
if( pkg->deleted && pkg->version_in_use != NULL && !ignoredelete ) {
r = target_removepackage(upgrade->target,refs,pkg->name,dereferencedfilekeys,NULL);
if( interupted() )
r = RET_ERROR_INTERUPTED;
else
r = target_removepackage(upgrade->target,refs,pkg->name,dereferencedfilekeys,NULL);
RET_UPDATE(result,r);
if( RET_WAS_ERROR(r) && force <= 0 )
break;
......@@ -572,6 +582,8 @@ void upgradelist_dump(struct upgradelist *upgrade){
assert(upgrade != NULL);
for( pkg = upgrade->list ; pkg != NULL ; pkg = pkg->next ) {
if( interupted() )
return;
if( pkg->deleted ) {
if( pkg->version_in_use != NULL &&
pkg->new_version != NULL ) {
......
......@@ -31,10 +31,10 @@ void upgradelist_dump(struct upgradelist *upgrade);
retvalue upgradelist_listmissing(struct upgradelist *upgrade,filesdb files);
/* Take all items in 'filename' into account, and remember them coming from 'method' */
retvalue upgradelist_update(struct upgradelist *upgrade,/*@dependent@*/struct aptmethod *method,const char *filename,upgrade_decide_function *predecide,void *decide_data,int force);
retvalue upgradelist_update(struct upgradelist *upgrade,/*@dependent@*/struct aptmethod *method,const char *filename,upgrade_decide_function *predecide,void *decide_data);
/* Take all items in source into account */
retvalue upgradelist_pull(struct upgradelist *upgrade,struct target *source,upgrade_decide_function *predecide,void *decide_data,int force, const char *dbdir);
retvalue upgradelist_pull(struct upgradelist *upgrade,struct target *source,upgrade_decide_function *predecide,void *decide_data,const char *dbdir);
/* mark all packages as deleted, so they will vanis unless readded or reholded */
retvalue upgradelist_deleteall(struct upgradelist *upgrade);
......
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