struct maildir_shindex_cache * maildir_shared_cache_read(struct maildir_shindex_cache *parent, const char *indexfile, const char *subhierarchy) { struct maildir_shindex_cache *p; if (parent && parent->next && subhierarchy && strcmp(parent->next->hierarchy, subhierarchy) == 0) { return parent->next; /* That was easy */ } if (!parent && shared_cache) { return shared_cache; } if (!indexfile) { indexfile=maildir_shared_index_file(); if (!indexfile) return NULL; subhierarchy=""; } if (!subhierarchy) return NULL; /* Should not happen, bad usage. subhierarchy allowed to be NULL only ** when indexfile is also NULL */ p=do_shared_cache_read(indexfile, subhierarchy); if (!p) return NULL; if (!parent) { shared_cache_free(shared_cache); shared_cache=p; } else { shared_cache_free(parent->next); parent->next=p; } return p; }
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; }