]> granicus.if.org Git - neomutt/commitdiff
This patch should fix the mailbox corruption various people observed.
authorThomas Roessler <roessler@does-not-exist.org>
Thu, 8 Jun 2000 21:44:14 +0000 (21:44 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Thu, 8 Jun 2000 21:44:14 +0000 (21:44 +0000)
copy.c
mbox.c

diff --git a/copy.c b/copy.c
index 6f7e22b336fb9da500d82be99fe52879a36e3b8d..5ae716c11479f8c13e8411752df1a75f80d7c480 100644 (file)
--- a/copy.c
+++ b/copy.c
@@ -297,6 +297,10 @@ mutt_copy_header (FILE *in, HEADER *h, FILE *out, int flags, const char *prefix)
     rfc822_cat(buffer, sizeof(buffer), Charset, MimeSpecials);
     fputs(buffer, out);
     fputc('\n', out);
+    
+    if (ferror (out) != 0 || feof (out) != 0)
+      return -1;
+    
   }
 
   if (flags & CH_UPDATE)
@@ -362,6 +366,9 @@ mutt_copy_header (FILE *in, HEADER *h, FILE *out, int flags, const char *prefix)
       return (-1);
   }
 
+  if (ferror (out) || feof (out))
+    return -1;
+  
   return (0);
 }
 
@@ -453,7 +460,7 @@ _mutt_copy_message (FILE *fpout, FILE *fpin, HEADER *hdr, BODY *body,
        new_lines = 0;
       else
        fprintf (fpout, "Lines: %d\n\n", new_lines);
-      if (ferror (fpout))
+      if (ferror (fpout) || feof (fpout))
        return -1;
       new_offset = ftell (fpout);
 
@@ -583,7 +590,12 @@ mutt_copy_message (FILE *fpout, CONTEXT *src, HEADER *hdr, int flags,
   
   if ((msg = mx_open_message (src, hdr->msgno)) == NULL)
     return -1;
-  r = _mutt_copy_message (fpout, msg->fp, hdr, hdr->content, flags, chflags);
+  if ((r = _mutt_copy_message (fpout, msg->fp, hdr, hdr->content, flags, chflags)) == 0 
+      && (ferror (fpout) || feof (fpout)))
+  {
+    dprint (1, (debugfile, "_mutt_copy_message failed to detect EOF!\n"));
+    r = -1;
+  }
   mx_close_message (&msg);
   return r;
 }
diff --git a/mbox.c b/mbox.c
index 6897874b80179e3a00965ed54807a75e4a9e9325..897e1bd6cccf6357b858678e9b0bfe30d64375fb 100644 (file)
--- a/mbox.c
+++ b/mbox.c
 /* struct used by mutt_sync_mailbox() to store new offsets */
 struct m_update_t
 {
+  short valid;
   long hdr;
   long body;
+  long lines;
+  long length;
 };
 
 /* parameters:
@@ -669,11 +672,12 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
   int i, j, save_sort = SORT_ORDER;
   int rc = -1;
   int need_sort = 0; /* flag to resort mailbox if new mail arrives */
-  int first;   /* first message to be written */
+  int first = -1;      /* first message to be written */
   long offset; /* location in mailbox to write changed messages */
   struct stat statbuf;
   struct utimbuf utimebuf;
   struct m_update_t *newOffset = NULL;
+  struct m_update_t *oldOffset = NULL;
   FILE *fp = NULL;
 
   /* sort message by their position in the mailbox on disk */
@@ -729,6 +733,7 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
       unlink (tempfile);
     }
     mutt_error _("Could not create temporary file!");
+    sleep (5);
     goto bail;
   }
 
@@ -766,6 +771,7 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
   
   /* allocate space for the new offsets */
   newOffset = safe_calloc (ctx->msgcount - first, sizeof (struct m_update_t));
+  oldOffset = safe_calloc (ctx->msgcount - first, sizeof (struct m_update_t));
 
   for (i = first, j = 0; i < ctx->msgcount; i++)
   {
@@ -780,6 +786,8 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
       {
        if (fputs (MMDF_SEP, fp) == EOF)
        {
+         mutt_perror (tempfile);
+         sleep (5);
          unlink (tempfile);
          goto bail;
        }
@@ -789,11 +797,24 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
       {
        if (fputs (KENDRA_SEP, fp) == EOF)
        {
+         mutt_perror (tempfile);
+         sleep (5);
          unlink (tempfile);
          goto bail;
        }
       }
 
+      /*
+       * back up some information which is needed to restore offsets when
+       * something fails.
+       */
+
+      oldOffset[i-first].valid  = 1;
+      oldOffset[i-first].hdr    = ctx->hdrs[i]->offset;
+      oldOffset[i-first].body   = ctx->hdrs[i]->content->offset;
+      oldOffset[i-first].lines  = ctx->hdrs[i]->lines;
+      oldOffset[i-first].length = ctx->hdrs[i]->content->length;
+      
       /* save the new offset for this message.  we add `offset' because the
        * temporary file only contains saved message which are located after
        * `offset' in the real mailbox
@@ -802,6 +823,8 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
 
       if (mutt_copy_message (fp, ctx, ctx->hdrs[i], M_CM_UPDATE, CH_FROM | CH_UPDATE | CH_UPDATE_LEN) == -1)
       {
+       mutt_perror (tempfile);
+       sleep (5);
        unlink (tempfile);
        goto bail;
       }
@@ -820,6 +843,8 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
        case M_MMDF: 
          if(fputs(MMDF_SEP, fp) == EOF) 
          {
+           mutt_perror (tempfile);
+           sleep (5);
            unlink (tempfile);
            goto bail; 
          }
@@ -827,6 +852,8 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
        case M_KENDRA:
          if(fputs(KENDRA_SEP, fp) == EOF)
          {
+           mutt_perror (tempfile);
+           sleep (5);
            unlink (tempfile);
            goto bail;
          }
@@ -834,6 +861,8 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
        default:
          if(fputs("\n", fp) == EOF) 
          {
+           mutt_perror (tempfile);
+           sleep (5);
            unlink (tempfile);
            goto bail;
          }
@@ -855,6 +884,8 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
   /* Save the state of this folder. */
   if (stat (ctx->path, &statbuf) == -1)
   {
+    mutt_perror (ctx->path);
+    sleep (5);
     unlink (tempfile);
     goto bail;
   }
@@ -955,6 +986,7 @@ int mbox_sync_mailbox (CONTEXT *ctx, int *index_hint)
     }
   }
   safe_free ((void **) &newOffset);
+  safe_free ((void **) &oldOffset);
   unlink (tempfile); /* remove partial copy of the mailbox */
   mutt_unblock_signals ();
   Sort = save_sort; /* Restore the default value. */
@@ -965,11 +997,25 @@ bail:  /* Come here in case of disaster */
 
   safe_fclose (&fp);
 
+  /* restore offsets, as far as they are valid */
+  if (first >= 0 && oldOffset)
+  {
+    for (i = first; i < ctx->msgcount && oldOffset[i-first].valid; i++)
+    {
+      ctx->hdrs[i]->offset = oldOffset[i-first].hdr;
+      ctx->hdrs[i]->content->hdr_offset = oldOffset[i-first].hdr;
+      ctx->hdrs[i]->content->offset = oldOffset[i-first].body;
+      ctx->hdrs[i]->lines = oldOffset[i-first].lines;
+      ctx->hdrs[i]->content->length = oldOffset[i-first].length;
+    }
+  }
+  
   /* this is ok to call even if we haven't locked anything */
   mbox_unlock_mailbox (ctx);
 
   mutt_unblock_signals ();
   safe_free ((void **) &newOffset);
+  safe_free ((void **) &oldOffset);
 
   if ((ctx->fp = freopen (ctx->path, "r", ctx->fp)) == NULL)
   {