make sync state header format less obscure

the header is not space-critical, so use proper name-value pairs.
this has the additional advantage that subsequent format changes can be
done much easier.
This commit is contained in:
Oswald Buddenhagen 2013-11-16 13:25:31 +01:00
parent 83bb1cf716
commit 48754ecc74
2 changed files with 111 additions and 49 deletions

View File

@ -364,16 +364,24 @@ sub showstate($)
}
chomp(my @ls = <FILE>);
close FILE;
$_ = shift(@ls);
if (!defined $_) {
print STDERR " Missing sync state header.\n";
my %hdr;
OUTER: while (1) {
while (@ls) {
$_ = shift(@ls);
last OUTER if (!length($_));
if (!/^([^ ]+) (\d+)$/) {
print STDERR "Malformed sync state header entry: $_\n";
close FILE;
return;
}
$hdr{$1} = $2;
}
print STDERR "Unterminated sync state header.\n";
close FILE;
return;
}
if (!/^1:(\d+) 1:(\d+):(\d+)$/) {
print STDERR " Malformed sync state header '$_'.\n";
return;
}
print " [ $1, $2, $3,\n ";
print " [ ".($hdr{'MaxPulledUid'} // "missing").", ".
($hdr{'MaxExpiredSlaveUid'} // "0").", ".($hdr{'MaxPushedUid'} // "missing").",\n ";
my $frst = 1;
for (@ls) {
if ($frst) {
@ -456,7 +464,8 @@ sub mkchan($$@)
&mkbox("slave", @{ $s });
open(FILE, ">", "slave/.mbsyncstate") or
die "Cannot create sync state.\n";
print FILE "1:".shift(@t)." 1:".shift(@t).":".shift(@t)."\n";
print FILE "MasterUidValidity 1\nMaxPulledUid ".shift(@t)."\n".
"SlaveUidValidity 1\nMaxExpiredSlaveUid ".shift(@t)."\nMaxPushedUid ".shift(@t)."\n\n";
while (@t) {
print FILE shift(@t)." ".shift(@t)." ".shift(@t)."\n";
}
@ -499,36 +508,56 @@ sub ckbox($$$@)
# $filename, @syncstate
sub ckstate($@)
{
my ($fn, @T) = @_;
my ($fn, $mmaxuid, $smaxxuid, $smaxuid, @T) = @_;
my %hdr;
$hdr{'MasterUidValidity'} = "1";
$hdr{'SlaveUidValidity'} = "1";
$hdr{'MaxPulledUid'} = $mmaxuid;
$hdr{'MaxPushedUid'} = $smaxuid;
$hdr{'MaxExpiredSlaveUid'} = $smaxxuid if ($smaxxuid ne 0);
open(FILE, "<", $fn) or die "Cannot read sync state $fn.\n";
my $l = <FILE>;
chomp(my @ls = <FILE>);
close FILE;
if (!defined $l) {
print STDERR "Sync state header missing.\n";
OUTER: while (1) {
while (@ls) {
my $l = shift(@ls);
last OUTER if (!length($l));
if ($l !~ /^([^ ]+) (\d+)$/) {
print STDERR "Malformed sync state header entry: $l\n";
return 1;
}
my $want = delete $hdr{$1};
if (!defined($want)) {
print STDERR "Unexpected sync state header entry: $1\n";
return 1;
}
if ($2 != $want) {
print STDERR "Sync state header entry $1 mismatch: got $2, wanted $want\n";
return 1;
}
}
print STDERR "Unterminated sync state header.\n";
return 1;
}
chomp($l);
my $xl = "1:".shift(@T)." 1:".shift(@T).":".shift(@T);
if ($l ne $xl) {
print STDERR "Sync state header mismatch: '$l' instead of '$xl'.\n";
my @ky = keys %hdr;
if (@ky) {
print STDERR "Keys missing from sync state header: @ky\n";
return 1;
} else {
for $l (@ls) {
if (!@T) {
print STDERR "Excess sync state entry: '$l'.\n";
return 1;
}
$xl = shift(@T)." ".shift(@T)." ".shift(@T);
if ($l ne $xl) {
print STDERR "Sync state entry mismatch: '$l' instead of '$xl'.\n";
return 1;
}
}
if (@T) {
print STDERR "Missing sync state entry: '".shift(@T)." ".shift(@T)." ".shift(@T)."'.\n";
}
for my $l (@ls) {
if (!@T) {
print STDERR "Excess sync state entry: '$l'.\n";
return 1;
}
my $xl = shift(@T)." ".shift(@T)." ".shift(@T);
if ($l ne $xl) {
print STDERR "Sync state entry mismatch: '$l' instead of '$xl'.\n";
return 1;
}
}
if (@T) {
print STDERR "Missing sync state entry: '".shift(@T)." ".shift(@T)." ".shift(@T)."'.\n";
return 1;
}
return 0;
}

View File

@ -30,6 +30,7 @@
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
@ -723,22 +724,51 @@ box_selected( int sts, void *aux )
}
if ((jfp = fopen( svars->dname, "r" ))) {
debug( "reading sync state %s ...\n", svars->dname );
if (!fgets( buf, sizeof(buf), jfp ) || !(t = strlen( buf )) || buf[t - 1] != '\n') {
error( "Error: incomplete sync state header in %s\n", svars->dname );
jbail:
fclose( jfp );
bail:
svars->ret = SYNC_FAIL;
sync_bail( svars );
return;
line = 0;
while (fgets( buf, sizeof(buf), jfp )) {
line++;
if (!(t = strlen( buf )) || buf[t - 1] != '\n') {
error( "Error: incomplete sync state header entry at %s:%d\n", svars->dname, line );
jbail:
fclose( jfp );
bail:
svars->ret = SYNC_FAIL;
sync_bail( svars );
return;
}
if (t == 1)
goto gothdr;
if (line == 1 && isdigit( buf[0] )) {
if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 ||
sscanf( buf1, "%d:%d", &svars->uidval[M], &svars->maxuid[M] ) < 2 ||
sscanf( buf2, "%d:%d:%d", &svars->uidval[S], &svars->smaxxuid, &svars->maxuid[S] ) < 3) {
error( "Error: invalid sync state header in %s\n", svars->dname );
goto jbail;
}
goto gothdr;
}
if (sscanf( buf, "%63s %d", buf1, &t1 ) != 2) {
error( "Error: malformed sync state header entry at %s:%d\n", svars->dname, line );
goto jbail;
}
if (!strcmp( buf1, "MasterUidValidity" ))
svars->uidval[M] = t1;
else if (!strcmp( buf1, "SlaveUidValidity" ))
svars->uidval[S] = t1;
else if (!strcmp( buf1, "MaxPulledUid" ))
svars->maxuid[M] = t1;
else if (!strcmp( buf1, "MaxPushedUid" ))
svars->maxuid[S] = t1;
else if (!strcmp( buf1, "MaxExpiredSlaveUid" ))
svars->smaxxuid = t1;
else {
error( "Error: unrecognized sync state header entry at %s:%d\n", svars->dname, line );
goto jbail;
}
}
if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 ||
sscanf( buf1, "%d:%d", &svars->uidval[M], &svars->maxuid[M] ) < 2 ||
sscanf( buf2, "%d:%d:%d", &svars->uidval[S], &svars->smaxxuid, &svars->maxuid[S] ) < 3) {
error( "Error: invalid sync state header in %s\n", svars->dname );
goto jbail;
}
line = 1;
error( "Error: unterminated sync state header in %s\n", svars->dname );
goto jbail;
gothdr:
while (fgets( buf, sizeof(buf), jfp )) {
line++;
if (!(t = strlen( buf )) || buf[t - 1] != '\n') {
@ -1747,9 +1777,12 @@ box_closed_p2( sync_vars_t *svars, int t )
}
}
Fprintf( svars->nfp, "%d:%d %d:%d:%d\n",
svars->uidval[M], svars->maxuid[M],
svars->uidval[S], svars->smaxxuid, svars->maxuid[S] );
Fprintf( svars->nfp,
"MasterUidValidity %d\nSlaveUidValidity %d\nMaxPulledUid %d\nMaxPushedUid %d\n",
svars->uidval[M], svars->uidval[S], svars->maxuid[M], svars->maxuid[S] );
if (svars->smaxxuid)
Fprintf( svars->nfp, "MaxExpiredSlaveUid %d\n", svars->smaxxuid );
Fprintf( svars->nfp, "\n" );
for (srec = svars->srecs; srec; srec = srec->next) {
if (srec->status & S_DEAD)
continue;