]> Pileus Git - ~andy/fetchmail/blobdiff - uid.c
Get rid of alloca() in fetchmail.
[~andy/fetchmail] / uid.c
diff --git a/uid.c b/uid.c
index 1d9846e03fe31b4a3ac5ad4bee7de532f059b8aa..ff993f59cbeb0d17fd829402c0fc8ea8cc741c63 100644 (file)
--- a/uid.c
+++ b/uid.c
@@ -134,7 +134,7 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
     if (lstat(idfile, &statbuf) < 0) {
        if (errno == ENOTDIR)
        {
-           report(stderr, GT_("lstat: %s: %s\n"), idfile, strerror(errno));
+           report(stderr, "lstat: %s: %s\n", idfile, strerror(errno));
            exit(PS_IOERR);
        }
     }
@@ -248,7 +248,7 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
                report_build(stdout, GT_("Old UID list from %s:"), 
                             ctl->server.pollname);
                for (idp = ctl->oldsaved; idp; idp = idp->next)
-                   report_build(stdout, " %s", idp->id);
+                   report_build(stdout, " %s", (char *)idp->id);
                if (!idp)
                    report_build(stdout, GT_(" <empty>"));
                report_complete(stdout, "\n");
@@ -259,7 +259,7 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
        {
            report_build(stdout, GT_("Scratch list of UIDs:"));
            for (idp = scratchlist; idp; idp = idp->next)
-               report_build(stdout, " %s", idp->id);
+               report_build(stdout, " %s", (char *)idp->id);
            if (!idp)
                report_build(stdout, GT_(" <empty>"));
            report_complete(stdout, "\n");
@@ -282,8 +282,9 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
        continue;
 
     *end = (struct idlist *)xmalloc(sizeof(struct idlist));
-    (*end)->val.status.mark = status;
     (*end)->id = (unsigned char *)str;
+    (*end)->val.status.mark = status;
+    (*end)->val.status.num = 0;
     (*end)->next = NULL;
 
     return end;
@@ -292,20 +293,21 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
 /* return the end list element for direct modification */
 struct idlist *save_str(struct idlist **idl, const char *str, flag st)
 {
-    return *save_str_quick(idl, str ? xstrdup(str) : NULL,
-                          st);
+    return *save_str_quick(idl, str ? xstrdup(str) : NULL, st);
 }
 
 void free_str_list(struct idlist **idl)
 /* free the given UID list */
 {
-    if (*idl == (struct idlist *)NULL)
-       return;
+    struct idlist *i = *idl;
 
-    free_str_list(&(*idl)->next);
-    free ((*idl)->id);
-    free(*idl);
-    *idl = (struct idlist *)NULL;
+    while(i) {
+       struct idlist *t = i->next;
+       free(i->id);
+       free(i);
+       i = t;
+    }
+    *idl = 0;
 }
 
 void save_str_pair(struct idlist **idl, const char *str1, const char *str2)
@@ -513,7 +515,7 @@ void uid_swap_lists(struct query *ctl)
        else
            report_build(stdout, GT_("New UID list from %s:"), ctl->server.pollname);
        for (idp = dofastuidl ? ctl->oldsaved : ctl->newsaved; idp; idp = idp->next)
-           report_build(stdout, " %s = %d", idp->id, idp->val.status.mark);
+           report_build(stdout, " %s = %d", (char *)idp->id, idp->val.status.mark);
        if (!idp)
            report_build(stdout, GT_(" <empty>"));
        report_complete(stdout, "\n");
@@ -538,11 +540,12 @@ void uid_swap_lists(struct query *ctl)
     if (ctl->newsaved)
     {
        /* old state of mailbox may now be irrelevant */
+       struct idlist *temp = ctl->oldsaved;
        if (outlevel >= O_DEBUG)
            report(stdout, GT_("swapping UID lists\n"));
-       free_str_list(&ctl->oldsaved);
        ctl->oldsaved = ctl->newsaved;
        ctl->newsaved = (struct idlist *) NULL;
+       free_str_list(&temp);
     }
     /* in fast uidl, there is no need to swap lists: the old state of
      * mailbox cannot be discarded! */
@@ -562,7 +565,7 @@ void uid_discard_new_list(struct query *ctl)
         * poll are marked here. */
        report_build(stdout, GT_("Merged UID list from %s:"), ctl->server.pollname);
        for (idp = ctl->oldsaved; idp; idp = idp->next)
-           report_build(stdout, " %s = %d", idp->id, idp->val.status.mark);
+           report_build(stdout, " %s = %d", (char *)idp->id, idp->val.status.mark);
        if (!idp)
            report_build(stdout, GT_(" <empty>"));
        report_complete(stdout, "\n");
@@ -608,25 +611,43 @@ void write_saved_lists(struct query *hostlist, const char *idfile)
     {
        if (outlevel >= O_DEBUG)
            report(stdout, GT_("Deleting fetchids file.\n"));
-       unlink(idfile);
-    }
-    else
-    {
+       if (unlink(idfile) && errno != ENOENT)
+           report(stderr, GT_("Error deleting %s: %s\n"), idfile, strerror(errno));
+    } else {
+       char *newnam = xmalloc(strlen(idfile) + 2);
+       strcpy(newnam, idfile);
+       strcat(newnam, "_");
        if (outlevel >= O_DEBUG)
            report(stdout, GT_("Writing fetchids file.\n"));
-       /* FIXME: do not overwrite the old idfile */
-       if ((tmpfp = fopen(idfile, "w")) != (FILE *)NULL) {
+       (void)unlink(newnam); /* remove file/link first */
+       if ((tmpfp = fopen(newnam, "w")) != (FILE *)NULL) {
+           int errflg;
            for (ctl = hostlist; ctl; ctl = ctl->next) {
                for (idp = ctl->oldsaved; idp; idp = idp->next)
                    if (idp->val.status.mark == UID_SEEN
                                || idp->val.status.mark == UID_DELETED)
                        fprintf(tmpfp, "%s@%s %s\n", 
-                           ctl->remotename, ctl->server.queryname, idp->id);
+                           ctl->remotename, ctl->server.queryname, (char *)idp->id);
            }
            for (idp = scratchlist; idp; idp = idp->next)
                fputs(idp->id, tmpfp);
+           fflush(tmpfp);
+           errflg = ferror(tmpfp);
            fclose(tmpfp);
+           /* if we could write successfully, move into place;
+            * otherwise, drop */
+           if (errflg) {
+               report(stderr, GT_("Error writing to fetchids file %s, old file left in place.\n"), newnam);
+               unlink(newnam);
+           } else {
+               if (rename(newnam, idfile)) {
+                   report(stderr, GT_("Cannot rename fetchids file %s to %s: %s\n"), newnam, idfile, strerror(errno));
+               }
+           }
+       } else {
+           report(stderr, GT_("Cannot open fetchids file %s for writing: %s\n"), newnam, strerror(errno));
        }
+       free(newnam);
     }
 }
 #endif /* POP3_ENABLE */