cope with out-of-disk-space halfways gracefully (that is, don't clobber

the sync state including the journal, but exit immediately).
This commit is contained in:
Oswald Buddenhagen 2004-11-13 09:19:36 +00:00
parent 556dfabc38
commit c2209c8470

View File

@ -33,6 +33,22 @@
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
void
Fprintf( FILE *f, const char *msg, ... )
{
int r;
va_list va;
va_start( va, msg );
r = vfprintf( f, msg, va );
va_end( va );
if (r < 0) {
perror( "cannot write file" );
exit( 1 );
}
}
static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' }; static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' };
static int static int
@ -256,10 +272,10 @@ sync_old( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
default: /* ok */ break; default: /* ok */ break;
case DRV_OK: case DRV_OK:
if (pull) { if (pull) {
fprintf( jfp, "< %d %d 0\n", srec->muid, srec->suid ); Fprintf( jfp, "< %d %d 0\n", srec->muid, srec->suid );
srec->muid = 0; srec->muid = 0;
} else { } else {
fprintf( jfp, "> %d %d 0\n", srec->muid, srec->suid ); Fprintf( jfp, "> %d %d 0\n", srec->muid, srec->suid );
srec->suid = 0; srec->suid = 0;
} }
} }
@ -290,10 +306,10 @@ sync_old( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
case DRV_OK: case DRV_OK:
if (pull) { if (pull) {
srec->suid = uid; srec->suid = uid;
fprintf( jfp, "> %d -1 %d\n", srec->muid, srec->suid ); Fprintf( jfp, "> %d -1 %d\n", srec->muid, srec->suid );
} else { } else {
srec->muid = uid; srec->muid = uid;
fprintf( jfp, "< -1 %d %d\n", srec->suid, srec->muid ); Fprintf( jfp, "< -1 %d %d\n", srec->suid, srec->muid );
} }
*nflags = smsg->flags; *nflags = smsg->flags;
} }
@ -344,7 +360,7 @@ sync_old( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
if (unex) { if (unex) {
debug( "unexpiring pair(%d,%d)\n", srec->muid, srec->suid ); debug( "unexpiring pair(%d,%d)\n", srec->muid, srec->suid );
/* log last, so deletion can't be misinterpreted! */ /* log last, so deletion can't be misinterpreted! */
fprintf( jfp, "~ %d %d 0\n", srec->muid, srec->suid ); Fprintf( jfp, "~ %d %d 0\n", srec->muid, srec->suid );
srec->status &= ~S_EXPIRED; srec->status &= ~S_EXPIRED;
} }
} }
@ -407,10 +423,10 @@ sync_new( int tops, store_t *sctx, store_t *tctx, store_conf_t *tconf, FILE *jfp
srec->next = 0; srec->next = 0;
**srecadd = srec; **srecadd = srec;
*srecadd = &srec->next; *srecadd = &srec->next;
fprintf( jfp, "+ %d %d %u\n", srec->muid, srec->suid, srec->flags ); Fprintf( jfp, "+ %d %d %u\n", srec->muid, srec->suid, srec->flags );
if (*smaxuid < msg->uid) { if (*smaxuid < msg->uid) {
*smaxuid = msg->uid; *smaxuid = msg->uid;
fprintf( jfp, pull ? "( %d\n" : ") %d\n", msg->uid ); Fprintf( jfp, pull ? "( %d\n" : ") %d\n", msg->uid );
} }
} }
} else } else
@ -522,7 +538,13 @@ sync_boxes( store_t *mctx, const char *mname,
} }
if ((dfp = fopen( dname, "r" ))) { if ((dfp = fopen( dname, "r" ))) {
debug( "reading sync state %s ...\n", dname ); debug( "reading sync state %s ...\n", dname );
if (fscanf( dfp, "%d:%d %d:%d:%d\n", &muidval, &mmaxuid, &suidval, &smaxxuid, &smaxuid) != 5) { if (!fgets( buf, sizeof(buf), dfp ) || !(i = strlen( buf )) || buf[i - 1] != '\n') {
fprintf( stderr, "Error: incomplete sync state header in %s\n", dname );
fclose( dfp );
ret = SYNC_FAIL;
goto bail;
}
if (sscanf( buf, "%d:%d %d:%d:%d", &muidval, &mmaxuid, &suidval, &smaxxuid, &smaxuid) != 5) {
fprintf( stderr, "Error: invalid sync state header in %s\n", dname ); fprintf( stderr, "Error: invalid sync state header in %s\n", dname );
fclose( dfp ); fclose( dfp );
ret = SYNC_FAIL; ret = SYNC_FAIL;
@ -531,8 +553,14 @@ sync_boxes( store_t *mctx, const char *mname,
line = 1; line = 1;
while (fgets( buf, sizeof(buf), dfp )) { while (fgets( buf, sizeof(buf), dfp )) {
line++; line++;
if (!(i = strlen( buf )) || buf[i - 1] != '\n') {
fprintf( stderr, "Error: incomplete sync state entry at %s:%d\n", dname, line );
fclose( dfp );
ret = SYNC_FAIL;
goto bail;
}
fbuf[0] = 0; fbuf[0] = 0;
if (sscanf( buf, "%d %d %15s\n", &t1, &t2, fbuf ) < 2) { if (sscanf( buf, "%d %d %15s", &t1, &t2, fbuf ) < 2) {
fprintf( stderr, "Error: invalid sync state entry at %s:%d\n", dname, line ); fprintf( stderr, "Error: invalid sync state entry at %s:%d\n", dname, line );
fclose( dfp ); fclose( dfp );
ret = SYNC_FAIL; ret = SYNC_FAIL;
@ -568,14 +596,20 @@ sync_boxes( store_t *mctx, const char *mname,
srec = recs; srec = recs;
while (fgets( buf, sizeof(buf), jfp )) { while (fgets( buf, sizeof(buf), jfp )) {
line++; line++;
if (!(i = strlen( buf )) || buf[i - 1] != '\n') {
fprintf( stderr, "Error: incomplete journal entry at %s:%d\n", jname, line );
fclose( jfp );
ret = SYNC_FAIL;
goto bail;
}
if (buf[0] == '^') if (buf[0] == '^')
srec = recs; srec = recs;
else { else {
if (buf[0] == '(' || buf[0] == ')' ? if (buf[0] == '(' || buf[0] == ')' ?
(sscanf( buf + 2, "%d\n", &t1 ) != 1) : (sscanf( buf + 2, "%d", &t1 ) != 1) :
buf[0] == '-' || buf[0] == '|' ? buf[0] == '-' || buf[0] == '|' ?
(sscanf( buf + 2, "%d %d\n", &t1, &t2 ) != 2) : (sscanf( buf + 2, "%d %d", &t1, &t2 ) != 2) :
(sscanf( buf + 2, "%d %d %d\n", &t1, &t2, &t3 ) != 3)) (sscanf( buf + 2, "%d %d %d", &t1, &t2, &t3 ) != 3))
{ {
fprintf( stderr, "Error: malformed journal entry at %s:%d\n", jname, line ); fprintf( stderr, "Error: malformed journal entry at %s:%d\n", jname, line );
fclose( jfp ); fclose( jfp );
@ -719,7 +753,7 @@ sync_boxes( store_t *mctx, const char *mname,
minwuid = srec->muid; minwuid = srec->muid;
} }
debug( " min non-orphaned master uid is %d\n", minwuid ); debug( " min non-orphaned master uid is %d\n", minwuid );
fprintf( jfp, "^\n" ); /* if any S_EXP_SLAVE */ Fprintf( jfp, "^\n" ); /* if any S_EXP_SLAVE */
for (srec = recs; srec; srec = srec->next) { for (srec = recs; srec; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;
@ -727,10 +761,10 @@ sync_boxes( store_t *mctx, const char *mname,
if (minwuid > srec->muid && mmaxuid >= srec->muid) { if (minwuid > srec->muid && mmaxuid >= srec->muid) {
debug( " -> killing (%d,%d)\n", srec->muid, srec->suid ); debug( " -> killing (%d,%d)\n", srec->muid, srec->suid );
srec->status = S_DEAD; srec->status = S_DEAD;
fprintf( jfp, "- %d %d\n", srec->muid, srec->suid ); Fprintf( jfp, "- %d %d\n", srec->muid, srec->suid );
} else if (srec->suid) { } else if (srec->suid) {
debug( " -> orphaning (%d,[%d])\n", srec->muid, srec->suid ); debug( " -> orphaning (%d,[%d])\n", srec->muid, srec->suid );
fprintf( jfp, "> %d %d 0\n", srec->muid, srec->suid ); Fprintf( jfp, "> %d %d 0\n", srec->muid, srec->suid );
srec->suid = 0; srec->suid = 0;
} }
} else if (minwuid > srec->muid) { } else if (minwuid > srec->muid) {
@ -738,7 +772,7 @@ sync_boxes( store_t *mctx, const char *mname,
if (mmaxuid >= srec->muid) { if (mmaxuid >= srec->muid) {
debug( " -> killing (%d,%d)\n", srec->muid, srec->suid ); debug( " -> killing (%d,%d)\n", srec->muid, srec->suid );
srec->status = S_DEAD; srec->status = S_DEAD;
fprintf( jfp, "- %d %d\n", srec->muid, srec->suid ); Fprintf( jfp, "- %d %d\n", srec->muid, srec->suid );
} }
} else if (srec->muid > 0 && srec->suid && (mctx->opts & OPEN_OLD) && } else if (srec->muid > 0 && srec->suid && (mctx->opts & OPEN_OLD) &&
(!(mctx->opts & OPEN_NEW) || mmaxuid >= srec->muid)) { (!(mctx->opts & OPEN_NEW) || mmaxuid >= srec->muid)) {
@ -785,12 +819,12 @@ sync_boxes( store_t *mctx, const char *mname,
if (!muidval || !suidval) { if (!muidval || !suidval) {
muidval = mctx->uidvalidity; muidval = mctx->uidvalidity;
suidval = sctx->uidvalidity; suidval = sctx->uidvalidity;
fprintf( jfp, "| %d %d\n", muidval, suidval ); Fprintf( jfp, "| %d %d\n", muidval, suidval );
} }
info( "Synchronizing\n" ); info( "Synchronizing\n" );
debug( "synchronizing old entries\n" ); debug( "synchronizing old entries\n" );
fprintf( jfp, "^\n" ); Fprintf( jfp, "^\n" );
for (srec = recs; srec; srec = srec->next) { for (srec = recs; srec; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;
@ -803,7 +837,7 @@ sync_boxes( store_t *mctx, const char *mname,
debug( " vanished\n" ); debug( " vanished\n" );
/* d.1) d.5) d.6) d.10) d.11) */ /* d.1) d.5) d.6) d.10) d.11) */
srec->status = S_DEAD; srec->status = S_DEAD;
fprintf( jfp, "- %d %d\n", srec->muid, srec->suid ); Fprintf( jfp, "- %d %d\n", srec->muid, srec->suid );
} else { } else {
delm = nom && (srec->muid > 0); delm = nom && (srec->muid > 0);
dels = nos && (srec->suid > 0); dels = nos && (srec->suid > 0);
@ -816,7 +850,7 @@ sync_boxes( store_t *mctx, const char *mname,
if (srec->flags != nflags) { if (srec->flags != nflags) {
debug( " updating flags (%u -> %u)\n", srec->flags, nflags ); debug( " updating flags (%u -> %u)\n", srec->flags, nflags );
srec->flags = nflags; srec->flags = nflags;
fprintf( jfp, "* %d %d %u\n", srec->muid, srec->suid, nflags ); Fprintf( jfp, "* %d %d %u\n", srec->muid, srec->suid, nflags );
} }
if (mmsg && (mmsg->flags & F_DELETED)) if (mmsg && (mmsg->flags & F_DELETED))
srec->status |= S_DEL_MASTER; srec->status |= S_DEL_MASTER;
@ -849,7 +883,7 @@ sync_boxes( store_t *mctx, const char *mname,
} }
} }
if (delt) { if (delt) {
fprintf( jfp, "^\n" ); Fprintf( jfp, "^\n" );
for (srec = recs; srec; srec = srec->next) { for (srec = recs; srec; srec = srec->next) {
if (srec->status & (S_DEAD|S_EXPIRED)) if (srec->status & (S_DEAD|S_EXPIRED))
continue; continue;
@ -857,7 +891,7 @@ sync_boxes( store_t *mctx, const char *mname,
if (smsg && (smsg->status & M_EXPIRED)) { if (smsg && (smsg->status & M_EXPIRED)) {
debug( " expiring pair(%d,%d)\n", srec->muid, srec->suid ); debug( " expiring pair(%d,%d)\n", srec->muid, srec->suid );
/* log first, so deletion can't be misinterpreted! */ /* log first, so deletion can't be misinterpreted! */
fprintf( jfp, "~ %d %d 1\n", srec->muid, srec->suid ); Fprintf( jfp, "~ %d %d 1\n", srec->muid, srec->suid );
if (smaxxuid < srec->suid) if (smaxxuid < srec->suid)
smaxxuid = srec->suid; smaxxuid = srec->suid;
srec->status |= S_EXPIRED; srec->status |= S_EXPIRED;
@ -914,7 +948,7 @@ sync_boxes( store_t *mctx, const char *mname,
debug( " min non-orphaned master uid is %d\n", minwuid ); debug( " min non-orphaned master uid is %d\n", minwuid );
} }
fprintf( jfp, "^\n" ); Fprintf( jfp, "^\n" );
for (srec = recs; srec; srec = srec->next) { for (srec = recs; srec; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;
@ -922,15 +956,15 @@ sync_boxes( store_t *mctx, const char *mname,
if (srec->muid <= 0 || ((srec->status & S_DEL_MASTER) && mex)) { if (srec->muid <= 0 || ((srec->status & S_DEL_MASTER) && mex)) {
debug( " -> killing (%d,%d)\n", srec->muid, srec->suid ); debug( " -> killing (%d,%d)\n", srec->muid, srec->suid );
srec->status = S_DEAD; srec->status = S_DEAD;
fprintf( jfp, "- %d %d\n", srec->muid, srec->suid ); Fprintf( jfp, "- %d %d\n", srec->muid, srec->suid );
} else if (srec->status & S_EXPIRED) { } else if (srec->status & S_EXPIRED) {
if (mmaxuid >= srec->muid && minwuid > srec->muid) { if (mmaxuid >= srec->muid && minwuid > srec->muid) {
debug( " -> killing (%d,%d)\n", srec->muid, srec->suid ); debug( " -> killing (%d,%d)\n", srec->muid, srec->suid );
srec->status = S_DEAD; srec->status = S_DEAD;
fprintf( jfp, "- %d %d\n", srec->muid, srec->suid ); Fprintf( jfp, "- %d %d\n", srec->muid, srec->suid );
} else if (srec->suid) { } else if (srec->suid) {
debug( " -> orphaning (%d,[%d])\n", srec->muid, srec->suid ); debug( " -> orphaning (%d,[%d])\n", srec->muid, srec->suid );
fprintf( jfp, "> %d %d 0\n", srec->muid, srec->suid ); Fprintf( jfp, "> %d %d 0\n", srec->muid, srec->suid );
srec->suid = 0; srec->suid = 0;
} }
} }
@ -939,12 +973,12 @@ sync_boxes( store_t *mctx, const char *mname,
} }
finish: finish:
fprintf( nfp, "%d:%d %d:%d:%d\n", muidval, mmaxuid, suidval, smaxxuid, smaxuid ); Fprintf( nfp, "%d:%d %d:%d:%d\n", muidval, mmaxuid, suidval, smaxxuid, smaxuid );
for (srec = recs; srec; srec = srec->next) { for (srec = recs; srec; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;
make_flags( srec->flags, fbuf ); make_flags( srec->flags, fbuf );
fprintf( nfp, "%d %d %s%s\n", srec->muid, srec->suid, Fprintf( nfp, "%d %d %s%s\n", srec->muid, srec->suid,
srec->status & S_EXPIRED ? "X" : "", fbuf ); srec->status & S_EXPIRED ? "X" : "", fbuf );
} }