aboutsummaryrefslogtreecommitdiffstats
path: root/uid.c
diff options
context:
space:
mode:
Diffstat (limited to 'uid.c')
-rw-r--r--uid.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/uid.c b/uid.c
index c54760e6..93fe8d26 100644
--- a/uid.c
+++ b/uid.c
@@ -23,8 +23,8 @@
/*
* Machinery for handling UID lists live here. This is mainly to support
- * RFC1725-conformant POP3 servers without a LAST command, but may also be
- * useful for making the IMAP4 querying logic UID-oriented, if a future
+ * RFC1725/RFC1939-conformant POP3 servers without a LAST command, but may also
+ * be useful for making the IMAP4 querying logic UID-oriented, if a future
* revision of IMAP forces me to.
*
* These functions are also used by the rest of the code to maintain
@@ -39,7 +39,7 @@
* This list is initially set up by initialize_saved_list() from the
* .fetchids file.
*
- * Early in the query, during the execution of the protocol-specific
+ * Early in the query, during the execution of the protocol-specific
* getrange code, the driver expects that the host's `newsaved' member
* will be filled with a list of UIDs and message numbers representing
* the mailbox state. If this list is empty, the server did
@@ -63,7 +63,7 @@
* be picked up by the next run. If there are no un-expunged
* messages, the file is deleted.
*
- * Note: some comparisons (those used for DNS address lists) are caseblind!
+ * Note: some comparisons (those used for DNS address lists) are caseblind!
*/
/* UIDs associated with un-queried hosts */
@@ -78,8 +78,12 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
struct query *ctl;
/* make sure lists are initially empty */
- for (ctl = hostlist; ctl; ctl = ctl->next)
- ctl->skipped = ctl->oldsaved = ctl->newsaved = (struct idlist *)NULL;
+ for (ctl = hostlist; ctl; ctl = ctl->next) {
+ ctl->skipped = (struct idlist *)NULL;
+ ctl->oldsaved = (struct idlist *)NULL;
+ ctl->newsaved = (struct idlist *)NULL;
+ ctl->oldsavedend = &ctl->oldsaved;
+ }
errno = 0;
@@ -91,13 +95,13 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
* that all implementations of lstat() will return ENOTDIR
* rather than plain ENOENT in this case...
*/
- if (lstat(idfile, &statbuf) < 0) {
- if (errno == ENOTDIR)
- {
- report(stderr, GT_("lstat: %s: %s\n"), idfile, strerror(errno));
- exit(PS_IOERR);
+ if (lstat(idfile, &statbuf) < 0) {
+ if (errno == ENOTDIR)
+ {
+ report(stderr, GT_("lstat: %s: %s\n"), idfile, strerror(errno));
+ exit(PS_IOERR);
+ }
}
- }
/* let's get stored message UIDs from previous queries */
if ((tmpfp = fopen(idfile, "r")) != (FILE *)NULL)
@@ -231,7 +235,11 @@ void initialize_saved_lists(struct query *hostlist, const char *idfile)
}
#endif /* POP3_ENABLE */
-struct idlist *save_str(struct idlist **idl, const char *str, flag status)
+/* return a pointer to the last element of the list to help the quick,
+ * constant-time addition to the list, NOTE: this function does not dup
+ * the string, the caller must do that. */
+/*@shared@*/ struct idlist **save_str_quick(/*@shared@*/ struct idlist **idl,
+ /*@only@*/ char *str, flag status)
/* save a number/UID pair on the given UID list */
{
struct idlist **end;
@@ -242,10 +250,17 @@ struct idlist *save_str(struct idlist **idl, const char *str, flag status)
*end = (struct idlist *)xmalloc(sizeof(struct idlist));
(*end)->val.status.mark = status;
- (*end)->id = str ? xstrdup(str) : (char *)NULL;
+ (*end)->id = (unsigned char *)str;
(*end)->next = NULL;
- return(*end);
+ return end;
+}
+
+/* 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);
}
void free_str_list(struct idlist **idl)
@@ -296,14 +311,17 @@ void free_str_pair_list(struct idlist **idl)
int str_in_list(struct idlist **idl, const char *str, const flag caseblind)
/* is a given ID in the given list? (comparison may be caseblind) */
{
- if (*idl == (struct idlist *)NULL || str == (char *) NULL)
- return(0);
- else if (!caseblind && strcmp(str, (*idl)->id) == 0)
- return(1);
- else if (caseblind && strcasecmp(str, (*idl)->id) == 0)
- return(1);
- else
- return(str_in_list(&(*idl)->next, str, caseblind));
+ struct idlist *walk;
+ if (caseblind) {
+ for( walk = *idl; walk; walk = walk->next )
+ if( strcasecmp( str, (char *)walk->id) == 0 )
+ return 1;
+ } else {
+ for( walk = *idl; walk; walk = walk->next )
+ if( strcmp( str, (char *)walk->id) == 0 )
+ return 1;
+ }
+ return 0;
}
int str_nr_in_list( struct idlist **idl, const char *str )
@@ -352,7 +370,7 @@ int count_list( struct idlist **idl)
return 1 + count_list( &(*idl)->next );
}
-char *str_from_nr_list(struct idlist **idl, int number)
+/*@null@*/ char *str_from_nr_list(struct idlist **idl, long number)
/* return the number'th string in idl */
{
if( !*idl || number < 0)
@@ -362,8 +380,8 @@ char *str_from_nr_list(struct idlist **idl, int number)
return str_from_nr_list(&(*idl)->next, number-1);
}
-
-char *str_find(struct idlist **idl, int number)
+
+char *str_find(struct idlist **idl, long number)
/* return the id of the given number in the given list. */
{
if (*idl == (struct idlist *) 0)
@@ -385,7 +403,7 @@ char *idpair_find(struct idlist **idl, const char *id)
return(idpair_find(&(*idl)->next, id));
}
-int delete_str(struct idlist **idl, int num)
+int delete_str(struct idlist **idl, long num)
/* delete given message from given list */
{
struct idlist *idp;
@@ -487,7 +505,7 @@ void uid_swap_lists(struct query *ctl)
void write_saved_lists(struct query *hostlist, const char *idfile)
/* perform end-of-run write of seen-messages list */
{
- int idcount;
+ long idcount;
FILE *tmpfp;
struct query *ctl;
struct idlist *idp;
@@ -495,10 +513,10 @@ void write_saved_lists(struct query *hostlist, const char *idfile)
/* if all lists are empty, nuke the file */
idcount = 0;
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)
- idcount++;
+ for (idp = ctl->oldsaved; idp; idp = idp->next)
+ if (idp->val.status.mark == UID_SEEN
+ || idp->val.status.mark == UID_DELETED)
+ idcount++;
}
/* either nuke the file or write updated last-seen IDs */
@@ -512,6 +530,7 @@ void write_saved_lists(struct query *hostlist, const char *idfile)
{
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) {
for (ctl = hostlist; ctl; ctl = ctl->next) {
for (idp = ctl->oldsaved; idp; idp = idp->next)