int maildir_newshared_nextAt(struct maildir_newshared_enum_cb *info, int *eof, int (*cb_func)(struct maildir_newshared_enum_cb*), void *cb_arg) { if (fseek(info->fp, info->startingpos, SEEK_SET) < 0) return -1; info->linenum= -1; return maildir_newshared_next(info, eof, cb_func, cb_arg); }
int maildir_newshared_enum(const char *indexfile, int (*cb_func)(struct maildir_newshared_enum_cb *), void *cb_arg) { struct maildir_newshared_enum_cb cb; int eof; int rc; if (maildir_newshared_open(indexfile, &cb) < 0) return -1; while ((rc=maildir_newshared_next(&cb, &eof, cb_func, cb_arg)) == 0) { if (eof) { maildir_newshared_close(&cb); return 0; } } maildir_newshared_close(&cb); return rc; }
static int list_newshared_shortcut(const char *skipped_pattern, struct list_sharable_info *shared_info, const char *acc_pfix, struct maildir_shindex_cache *parentCache, const char *indexfile, const char *subhierarchy) { struct list_newshared_info lni; int rc; struct maildir_shindex_cache *curcache=NULL; lni.acc_pfix=acc_pfix; lni.skipped_pattern=skipped_pattern; lni.shared_info=shared_info; lni.dorecurse=1; /* Try for some common optimization, to avoid expanding the ** entire #shared hierarchy, taking advantage of the cache list. */ for (;;) { const char *p; size_t i; char *q; int eof; if (strcmp(skipped_pattern, "%") == 0) { lni.dorecurse=0; break; } if (strncmp(skipped_pattern, "%" HIERCHS, sizeof("%" HIERCHS)-1) == 0) { curcache=maildir_shared_cache_read(parentCache, indexfile, subhierarchy); if (!curcache) return 0; lni.acc_pfix=acc_pfix; lni.skipped_pattern=skipped_pattern + sizeof("%" HIERCHS)-1; lni.parentCache=curcache; for (i=0; i<curcache->nrecords; i++) { if (i == 0) { curcache->indexfile.startingpos=0; rc=maildir_newshared_nextAt(&curcache->indexfile, &eof, list_newshared_skiplevel, &lni); } else rc=maildir_newshared_next(&curcache->indexfile, &eof, list_newshared_skiplevel, &lni); if (rc || eof) { fprintf(stderr, "ERR:maildir_newshared_next failed: %s\n", strerror(errno)); break; } } return 0; } for (p=skipped_pattern; *p; p++) if (*p == HIERCH || ((lni.shared_info->flags & LIST_CHECK1FOLDER) == 0 && (*p == '*' || *p == '%'))) break; if (*p && *p != HIERCH) break; curcache=maildir_shared_cache_read(parentCache, indexfile, subhierarchy); if (!curcache) return 0; for (i=0; i < curcache->nrecords; i++) { char *n=maildir_info_imapmunge(curcache->records[i] .name); if (!n) write_error_exit(0); if (strlen(n) == p-skipped_pattern && strncmp(n, skipped_pattern, p-skipped_pattern) == 0) { free(n); break; } free(n); } if (i >= curcache->nrecords) /* not found */ return 0; if (*p) ++p; q=malloc(strlen(acc_pfix)+(p-skipped_pattern)+1); if (!q) { write_error_exit(0); } strcpy(q, acc_pfix); strncat(q, skipped_pattern, p-skipped_pattern); lni.acc_pfix=q; lni.skipped_pattern=p; lni.parentCache=curcache; curcache->indexfile.startingpos=curcache->records[i].offset; rc=maildir_newshared_nextAt(&curcache->indexfile, &eof, list_newshared_skipcb, &lni); free(q); return rc; } if (!indexfile) indexfile=maildir_shared_index_file(); rc=maildir_newshared_enum(indexfile, list_newshared_cb, &lni); return rc; }
static struct maildir_shindex_cache *do_shared_cache_read(const char *indexfile, const char *subhier) { struct maildir_shindex_temp_record *rec=NULL; size_t n; struct maildir_shindex_cache *c; int eof; int rc; if ((c=malloc(sizeof(struct maildir_shindex_cache))) == NULL || (c->hierarchy=strdup(subhier)) == NULL) { if (c) free(c); perror("malloc"); return NULL; } if (maildir_newshared_open(indexfile, &c->indexfile) < 0) { free(c->hierarchy); free(c); return NULL; } n=0; while ((rc=maildir_newshared_next(&c->indexfile, &eof, shared_cache_read_cb, &rec)) == 0) { if (eof) break; ++n; } if (rc) { free(c->hierarchy); free(c); while (rec) { struct maildir_shindex_temp_record *r=rec; rec=rec->next; free(r->rec.name); free(r); } return NULL; } /* Now, convert from list to array */ c->nrecords=n; c->records=NULL; c->next=NULL; if (n) { if ((c->records=malloc(sizeof(*c->records)*n)) == NULL) { free(c->hierarchy); free(c); while (rec) { struct maildir_shindex_temp_record *r=rec; rec=rec->next; free(r->rec.name); free(r); } return NULL; } n=0; while (rec) { struct maildir_shindex_temp_record *r=rec; rec=rec->next; c->records[n]= r->rec; free(r); ++n; } } return c; }