Back to index

courier  0.68.2
maildirnewshared2.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2004-2007 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 #include      <stdio.h>
00010 #include      <stdlib.h>
00011 #include      <string.h>
00012 #include      <errno.h>
00013 #include      <ctype.h>
00014 #include      <fcntl.h>
00015 #if    HAVE_UNISTD_H
00016 #include      <unistd.h>
00017 #endif
00018 #if    HAVE_UTIME_H
00019 #include      <utime.h>
00020 #endif
00021 #if TIME_WITH_SYS_TIME
00022 #include      <sys/time.h>
00023 #include      <time.h>
00024 #else
00025 #if HAVE_SYS_TIME_H
00026 #include      <sys/time.h>
00027 #else
00028 #include      <time.h>
00029 #endif
00030 #endif
00031 
00032 #include      <sys/types.h>
00033 #include      <sys/stat.h>
00034 
00035 #include      "config.h"
00036 #include      "maildir/maildirnewshared.h"
00037 
00038 
00039 static struct maildir_shindex_cache *shared_cache=NULL;
00040 
00041 static void shared_cache_free(struct maildir_shindex_cache *c)
00042 {
00043        while (c)
00044        {
00045               struct maildir_shindex_cache *p=c;
00046               size_t i;
00047 
00048               c=c->next;
00049 
00050               free(p->hierarchy);
00051               if (p->records)
00052               {
00053                      for (i=0; i<p->nrecords; i++)
00054                             free(p->records[i].name);
00055                      free(p->records);
00056               }
00057               maildir_newshared_close(&p->indexfile);
00058               free(p);
00059        }
00060 }
00061 
00062 static struct maildir_shindex_cache *do_shared_cache_read(const char *indexfile,
00063                                                  const char *subhier);
00064 
00065 struct maildir_shindex_cache *
00066 maildir_shared_cache_read(struct maildir_shindex_cache *parent,
00067                        const char *indexfile,
00068                        const char *subhierarchy)
00069 {
00070        struct maildir_shindex_cache *p;
00071 
00072        if (parent && parent->next && subhierarchy &&
00073            strcmp(parent->next->hierarchy, subhierarchy) == 0)
00074        {
00075               return parent->next; /* That was easy */
00076        }
00077 
00078        if (!parent && shared_cache)
00079        {
00080               return shared_cache;
00081        }
00082 
00083        if (!indexfile)
00084        {
00085               indexfile=maildir_shared_index_file();
00086               if (!indexfile)
00087                      return NULL;
00088               subhierarchy="";
00089        }
00090 
00091 
00092        if (!subhierarchy)
00093               return NULL;
00094        /* Should not happen, bad usage. subhierarchy allowed to be NULL only
00095        ** when indexfile is also NULL */
00096 
00097        p=do_shared_cache_read(indexfile, subhierarchy);
00098 
00099        if (!p)
00100               return NULL;
00101 
00102        if (!parent)
00103        {
00104               shared_cache_free(shared_cache);
00105               shared_cache=p;
00106        }
00107        else
00108        {
00109               shared_cache_free(parent->next);
00110               parent->next=p;
00111        }
00112        return p;
00113 }
00114 
00115 struct maildir_shindex_temp_record {
00116        struct maildir_shindex_temp_record *next;
00117        struct maildir_shindex_record rec;
00118 };
00119 
00120 static int shared_cache_read_cb(struct maildir_newshared_enum_cb *ptr)
00121 {
00122        struct maildir_shindex_temp_record *r;
00123        struct maildir_shindex_temp_record **list=
00124               (struct maildir_shindex_temp_record **)ptr->cb_arg;
00125 
00126        if ((r=malloc(sizeof(struct maildir_shindex_temp_record))) == NULL ||
00127            (r->rec.name=strdup(ptr->name)) == NULL)
00128        {
00129               if (r)
00130                      free(r);
00131               perror("malloc");
00132               return -1;
00133        }
00134 
00135        r->rec.offset=ptr->startingpos;
00136        r->next= *list;
00137        *list=r;
00138        return 0;
00139 }
00140 
00141 static struct maildir_shindex_cache *do_shared_cache_read(const char *indexfile,
00142                                                  const char *subhier)
00143 {
00144        struct maildir_shindex_temp_record *rec=NULL;
00145        size_t n;
00146        struct maildir_shindex_cache *c;
00147        int eof;
00148        int rc;
00149 
00150        if ((c=malloc(sizeof(struct maildir_shindex_cache))) == NULL ||
00151            (c->hierarchy=strdup(subhier)) == NULL)
00152        {
00153               if (c)
00154                      free(c);
00155               perror("malloc");
00156               return NULL;
00157        }
00158 
00159        if (maildir_newshared_open(indexfile, &c->indexfile) < 0)
00160        {
00161               free(c->hierarchy);
00162               free(c);
00163               return NULL;
00164        }
00165 
00166        n=0;
00167 
00168        while ((rc=maildir_newshared_next(&c->indexfile, &eof,
00169                                      shared_cache_read_cb, &rec)) == 0)
00170        {
00171               if (eof)
00172                      break;
00173               ++n;
00174        }
00175 
00176        if (rc)
00177        {
00178               free(c->hierarchy);
00179               free(c);
00180               while (rec)
00181               {
00182                      struct maildir_shindex_temp_record *r=rec;
00183 
00184                      rec=rec->next;
00185 
00186                      free(r->rec.name);
00187                      free(r);
00188               }
00189               return NULL;
00190        }
00191 
00192        /* Now, convert from list to array */
00193 
00194        c->nrecords=n;
00195        c->records=NULL;
00196        c->next=NULL;
00197 
00198        if (n)
00199        {
00200               if ((c->records=malloc(sizeof(*c->records)*n)) == NULL)
00201               {
00202 
00203                      free(c->hierarchy);
00204                      free(c);
00205                      while (rec)
00206                      {
00207                             struct maildir_shindex_temp_record *r=rec;
00208 
00209                             rec=rec->next;
00210 
00211                             free(r->rec.name);
00212                             free(r);
00213                      }
00214                      return NULL;
00215               }
00216 
00217               n=0;
00218               while (rec)
00219               {
00220                      struct maildir_shindex_temp_record *r=rec;
00221 
00222                      rec=rec->next;
00223                      c->records[n]= r->rec;
00224 
00225                      free(r);
00226                      ++n;
00227               }
00228        }
00229 
00230        return c;
00231 }
00232 
00233 
00234 
00235 
00236 
00237