Back to index

courier  0.68.2
maildirshared.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2000-2007 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if HAVE_CONFIG_H
00007 #include "config.h"
00008 #endif
00009 
00010 #include <sys/types.h>
00011 #if HAVE_DIRENT_H
00012 #include <dirent.h>
00013 #define NAMLEN(dirent) strlen((dirent)->d_name)
00014 #else
00015 #define dirent direct
00016 #define NAMLEN(dirent) (dirent)->d_namlen
00017 #if HAVE_SYS_NDIR_H
00018 #include <sys/ndir.h>
00019 #endif
00020 #if HAVE_SYS_DIR_H
00021 #include <sys/dir.h>
00022 #endif
00023 #if HAVE_NDIR_H
00024 #include <ndir.h>
00025 #endif
00026 #endif
00027 #include      <sys/types.h>
00028 #include      <sys/stat.h>
00029 #include      <string.h>
00030 #include      <stdlib.h>
00031 #include      <time.h>
00032 #if    HAVE_UNISTD_H
00033 #include      <unistd.h>
00034 #endif
00035 #include      <stdio.h>
00036 #include      <ctype.h>
00037 #include      <errno.h>
00038 #include      <fcntl.h>
00039 
00040 #include      "maildirmisc.h"
00041 #include      "maildircreate.h"
00042 #include      "maildirsharedrc.h"
00043 
00044 
00045 /* Prerequisited for shared folder support */
00046 
00047 #if    HAVE_READLINK
00048 #if    HAVE_SYMLINK
00049 #if    HAVE_DBOBJ
00050 
00051 #define       YES_WE_CAN_DO_SHARED 1
00052 
00053 #endif
00054 #endif
00055 #endif
00056 
00057 #if    YES_WE_CAN_DO_SHARED
00058 
00059 #include      "dbobj.h"
00060 
00061 static void list_sharable(const char *, const char *,
00062        void (*)(const char *, void *),
00063        void *);
00064 
00065 extern FILE *maildir_shared_fopen(const char *, const char *);
00066 extern void maildir_shared_fparse(char *, char **, char **);
00067 
00068 void maildir_list_sharable(const char *maildir,
00069        void (*func)(const char *, void *),
00070        void *voidp)
00071 {
00072 char   buf[BUFSIZ];
00073 FILE   *fp;
00074 char   *p;
00075 int    pass;
00076 
00077        if (!maildir) maildir=".";
00078 
00079        for (pass=0; pass<2; pass++)
00080        {
00081               fp=pass ? maildir_shared_fopen(maildir, "r")
00082                      : fopen (MAILDIRSHAREDRC, "r");
00083 
00084               if (!fp)      continue;
00085 
00086               while ((p=fgets(buf, sizeof(buf), fp)) != 0)
00087               {
00088               char   *name, *dir;
00089 
00090                      maildir_shared_fparse(p, &name, &dir);
00091                      if (name)
00092                             list_sharable(name, dir, func, voidp);
00093               }
00094               fclose(fp);
00095        }
00096 }
00097 
00098 static void list_sharable(const char *pfix, const char *path,
00099        void (*func)(const char *, void *),
00100        void *voidp)
00101 {
00102 DIR    *dirp;
00103 struct dirent *de;
00104 struct stat   stat_buf;
00105 
00106        dirp=opendir(path);
00107        while (dirp && (de=readdir(dirp)) != 0)
00108        {
00109        char   *z;
00110 
00111               if (de->d_name[0] != '.')   continue;
00112               if (strcmp(de->d_name, ".") == 0 ||
00113                      strcmp(de->d_name, "..") == 0)     continue;
00114 
00115               z=malloc(strlen(path)+strlen(de->d_name)+12);
00116               if (!z)       continue;
00117 
00118               strcat(strcat(strcat(strcpy(z, path),
00119                      "/"), de->d_name), "/cur/.");
00120 
00121               if (stat(z, &stat_buf))
00122               {
00123                      free(z);
00124                      continue;
00125               }
00126               free(z);
00127               z=malloc(strlen(pfix)+strlen(de->d_name)+1);
00128               if (!z)       continue;
00129               strcat(strcpy(z, pfix), de->d_name);
00130               (*func)(z, voidp);
00131               free(z);
00132        }
00133        if (dirp)     closedir(dirp);
00134 }
00135 
00136 int maildir_shared_subscribe(const char *maildir, const char *folder)
00137 {
00138 char   linebuf[BUFSIZ];
00139 FILE   *fp;
00140 char   *p;
00141 char   *name=strchr(folder, '.');
00142 char   *s, *n, *dir;
00143 char   *buf, *link;
00144 unsigned l;
00145 int    pass;
00146 
00147        if (!name)
00148        {
00149               errno=EINVAL;
00150               return (-1);
00151        }
00152 
00153        if (!maildir) maildir=".";
00154        p=maildir_shareddir(maildir, folder);     /* valid folder name? */
00155        if (!p)
00156        {
00157               errno=EINVAL;
00158               return (-1);
00159        }
00160        free(p);
00161 
00162        p=0;
00163 
00164        for (pass=0; pass<2; pass++)
00165        {
00166               fp=pass ? maildir_shared_fopen(maildir, "r")
00167                      : fopen (MAILDIRSHAREDRC, "r");
00168 
00169               if (!fp)      continue;
00170 
00171               while ((p=fgets(linebuf, sizeof(linebuf), fp)) != 0)
00172               {
00173                      maildir_shared_fparse(p, &n, &dir);
00174 
00175                      if (!n)       continue;
00176 
00177                      if (strlen(n) == name - folder &&
00178                             memcmp(n, folder, name-folder) == 0)      break;
00179               }
00180               fclose(fp);
00181 
00182               if (p) break;
00183        }
00184 
00185        if (p)
00186        {
00187               /*
00188               ** We will create:
00189               **
00190               **  maildir/shared-folders/ (name-folder) /(name)
00191               **
00192               **  there we'll have subdirs cur/new/tmp  and shared link
00193               */
00194 
00195               l=sizeof("/" SHAREDSUBDIR "//shared") +
00196                      strlen(maildir) + strlen(folder);
00197               buf=malloc(l);
00198               if (!buf)     return (-1);
00199               strcat(strcpy(buf, maildir), "/" SHAREDSUBDIR);
00200               mkdir(buf, 0700);
00201               strcat(buf, "/");
00202               strncat(buf, folder, name-folder);
00203               mkdir(buf, 0700);
00204               strcat(buf, "/");
00205               strcat(buf, name+1);
00206               if ( mkdir(buf, 0700))      return (-1);
00207               s=buf+strlen(buf);
00208               *s++='/';
00209               strcpy(s, "tmp");
00210               if ( mkdir(buf, 0700))
00211               {
00212                      s[-1]=0;
00213                      rmdir(buf);
00214                      free(buf);
00215                      return (-1);
00216               }
00217               strcpy(s, "cur");
00218               if ( mkdir(buf, 0700))
00219               {
00220                      strcpy(s, "tmp");
00221                      rmdir(buf);
00222                      s[-1]=0;
00223                      rmdir(buf);
00224                      free(buf);
00225                      return (-1);
00226               }
00227               strcpy(s, "new");
00228               if ( mkdir(buf, 0700))
00229               {
00230                      strcpy(s, "cur");
00231                      rmdir(buf);
00232                      strcpy(s, "tmp");
00233                      rmdir(buf);
00234                      s[-1]=0;
00235                      rmdir(buf);
00236                      free(buf);
00237                      return (-1);
00238               }
00239 
00240               strcpy(s, "shared");
00241               if ((link=malloc(strlen(dir)+strlen(name)+2)) == 0 ||
00242                      symlink( strcat(strcat(strcpy(link, dir), "/"), name),
00243                             buf))
00244               {
00245                      if (link)     free(link);
00246                      strcpy(s, "new");
00247                      rmdir(buf);
00248                      strcpy(s, "cur");
00249                      rmdir(buf);
00250                      strcpy(s, "tmp");
00251                      rmdir(buf);
00252                      s[-1]=0;
00253                      rmdir(buf);
00254                      free(buf);
00255                      return (-1);
00256               }
00257               free(link);
00258               free(buf);
00259               return (0);
00260        }
00261        errno=ENOENT;
00262        return (-1);
00263 }
00264 
00265 void maildir_list_shared(const char *maildir,
00266        void (*func)(const char *, void *),
00267        void *voidp)
00268 {
00269 char   *sh;
00270 DIR    *dirp;
00271 struct dirent *de;
00272 
00273        if (!maildir) maildir=".";
00274        sh=malloc(strlen(maildir)+sizeof("/" SHAREDSUBDIR));
00275        if (!sh)      return;
00276 
00277        strcat(strcpy(sh, maildir), "/" SHAREDSUBDIR);
00278 
00279        dirp=opendir(sh);
00280        while (dirp && (de=readdir(dirp)) != 0)
00281        {
00282        DIR    *dirp2;
00283        struct dirent *de2;
00284        char   *z;
00285 
00286               if (de->d_name[0] == '.')   continue;
00287 
00288               z=malloc(strlen(sh)+strlen(de->d_name)+2);
00289               if (!z)       continue;
00290               strcat(strcat(strcpy(z, sh), "/"), de->d_name);
00291               dirp2=opendir(z);
00292               free(z);
00293 
00294               while (dirp2 && (de2=readdir(dirp2)) != 0)
00295               {
00296               char   *s;
00297 
00298                      if (de2->d_name[0] == '.')  continue;
00299                      s=malloc(strlen(de->d_name)+strlen(de2->d_name)+2);
00300                      if (!s)       continue;
00301                      strcat(strcat(strcpy(s, de->d_name), "."), de2->d_name);
00302                      (*func)(s, voidp);
00303                      free(s);
00304               }
00305               if (dirp2)    closedir(dirp2);
00306        }
00307        free(sh);
00308        if (dirp)     closedir(dirp);
00309 }
00310 
00311 int maildir_shared_unsubscribe(const char *maildir, const char *folder)
00312 {
00313 char   *s;
00314 
00315        s=maildir_shareddir(maildir, folder);
00316        if (!s)       return (-1);
00317 
00318        if (maildir_del(s))
00319        {
00320               free(s);
00321               return (-1);
00322        }
00323        *strrchr(s, '/')=0;  /* Try to remove the whole folder dir */
00324        rmdir(s);
00325        free(s);
00326        return (0);
00327 }
00328 
00329 /*                    LET'S SYNC IT                  */
00330 
00331 static void do_maildir_shared_sync(const char *, const char *);
00332 
00333 void maildir_shared_sync(const char *dir)
00334 {
00335 char   *shareddir;
00336 char   *buf;
00337 
00338        shareddir=malloc(strlen(dir)+sizeof("/shared"));
00339        if (!shareddir)
00340        {
00341               perror("malloc");
00342               return;
00343        }
00344        strcat(strcpy(shareddir, dir),"/shared");
00345 
00346        buf=maildir_getlink(shareddir);
00347        free(shareddir);
00348        if (buf)
00349        {
00350               do_maildir_shared_sync(dir, buf);
00351               free(buf);
00352        }
00353 }
00354 
00355 /* Step 1 - safely create a temporary database */
00356 
00357 static int create_db(struct dbobj *obj,
00358        const char *dir,
00359        char **dbname)
00360 {
00361        struct maildir_tmpcreate_info createInfo;
00362 
00363        maildir_tmpcreate_init(&createInfo);
00364 
00365        createInfo.maildir=dir;
00366        createInfo.uniq="sync";
00367        createInfo.doordie=1;
00368 
00369        {
00370               int    fd;
00371 
00372               fd=maildir_tmpcreate_fd(&createInfo);
00373 
00374               if (fd < 0)
00375               {
00376                      perror(dir);
00377                      return -1;
00378               }
00379               close(fd);
00380 
00381               dbobj_init(obj);
00382               if (dbobj_open(obj, createInfo.tmpname, "N") < 0)
00383               {
00384                      perror(createInfo.tmpname);
00385                      unlink(createInfo.tmpname);
00386                      maildir_tmpcreate_free(&createInfo);
00387                      return (-1);
00388               }
00389        }
00390 
00391        *dbname=createInfo.tmpname;
00392        createInfo.tmpname=NULL;
00393        maildir_tmpcreate_free(&createInfo);
00394        return (0);
00395 }
00396 
00397 /*
00398 ** Populate the DB by building the db with the messages in the sharable
00399 ** folder's cur.  The key is the stripped message filename, the value is
00400 ** the complete message filename.
00401 */
00402 
00403 static int build_db(const char *shared, struct dbobj *obj)
00404 {
00405 char   *dummy=malloc(strlen(shared)+sizeof("/cur"));
00406 DIR    *dirp;
00407 struct dirent *de;
00408 
00409        if (!dummy)
00410        {
00411               perror("malloc");
00412               return (-1);
00413        }
00414 
00415        strcat(strcpy(dummy, shared), "/cur");
00416 
00417        dirp=opendir(dummy);
00418        while (dirp && (de=readdir(dirp)) != 0)
00419        {
00420        char   *a, *b;
00421        char   *c;
00422 
00423               if (de->d_name[0] == '.')
00424                      continue;
00425               if ((a=malloc(strlen(de->d_name)+1)) == 0)
00426               {
00427                      perror("malloc");
00428                      closedir(dirp);
00429                      free(dummy);
00430                      return (-1);
00431               }
00432               if ((b=malloc(strlen(de->d_name)+1)) == 0)
00433               {
00434                      perror("malloc");
00435                      closedir(dirp);
00436                      free(dummy);
00437                      free(a);
00438                      return (-1);
00439               }
00440               strcpy(a, de->d_name);
00441               strcpy(b, de->d_name);
00442               c=strrchr(a, MDIRSEP[0]);
00443               if (c) *c=0;
00444 
00445               if (dbobj_store(obj, a, strlen(a), b, strlen(b), "R"))
00446               {
00447                      perror("dbobj_store");
00448                      free(a);
00449                      free(b);
00450                      closedir(dirp);
00451                      free(dummy);
00452                      return (-1);
00453               }
00454               free(a);
00455               free(b);
00456        }
00457        if (dirp)     closedir(dirp);
00458        free(dummy);
00459        return (0);
00460 }
00461 
00462 static int update_link(const char *,
00463        const char *, const char *,
00464        const char *,
00465        const char *,
00466        size_t);
00467 
00468 /*
00469 **     Now, read our synced cur directory, and make sure that the soft
00470 **     links are up to date.  Remove messages that have been deleted from
00471 **     the sharable maildir, and make sure that the remaining links are
00472 **     valid.
00473 */
00474 
00475 static int update_cur(const char *cur, const char *shared, struct dbobj *obj)
00476 {
00477 DIR    *dirp;
00478 struct dirent *de;
00479 char   *p;
00480 
00481        dirp=opendir(cur);
00482        while (dirp && (de=readdir(dirp)) != 0)
00483        {
00484        char   *cur_base;
00485 
00486        char   *cur_name_ptr;
00487        size_t cur_name_len;
00488 
00489        char   *linked_name_buf;
00490        size_t linked_name_len;
00491        int    n;
00492 
00493               if (de->d_name[0] == '.')   continue;
00494 
00495               /*
00496               ** Strip the maildir flags, and look up the message in the
00497               ** db.
00498               */
00499 
00500               cur_base=malloc(strlen(de->d_name)+1);
00501               if (!cur_base)
00502               {
00503                      perror("malloc");
00504                      closedir(dirp);
00505                      return (-1);
00506               }
00507               strcpy(cur_base, de->d_name);
00508               p=strrchr(cur_base, MDIRSEP[0]);
00509               if (p) *p=0;
00510 
00511               cur_name_ptr=dbobj_fetch(obj, cur_base, strlen(cur_base),
00512                      &cur_name_len, "");
00513 
00514               /* If it's there, delete the db entry. */
00515 
00516               if (cur_name_ptr)
00517                      dbobj_delete(obj, cur_base, strlen(cur_base));
00518 
00519               /*
00520               ** We'll either delete this soft link, or check its
00521               ** contents, so we better build its complete pathname in
00522               ** any case.
00523               */
00524 
00525               free(cur_base);
00526               cur_base=malloc(strlen(de->d_name)+strlen(cur)+2);
00527               if (!cur_base)
00528               {
00529                      perror("malloc");
00530                      if (cur_name_ptr)    free(cur_name_ptr);
00531                      closedir(dirp);
00532                      return (-1);
00533               }
00534               strcat(strcat(strcpy(cur_base, cur), "/"), de->d_name);
00535 
00536               if (!cur_name_ptr)   /* Removed from sharable dir */
00537               {
00538                      unlink(cur_base);
00539                      free(cur_base);
00540                      continue;
00541               }
00542 
00543               linked_name_len=strlen(shared)+strlen(de->d_name)+100;
00544                      /* should be enough */
00545 
00546               if ((linked_name_buf=malloc(linked_name_len)) == 0)
00547               {
00548                      perror("malloc");
00549                      free(cur_base);
00550                      free(cur_name_ptr);
00551                      closedir(dirp);
00552                      return (-1);
00553               }
00554 
00555               if ((n=readlink(cur_base, linked_name_buf, linked_name_len))< 0)
00556               {
00557                      /* This is stupid, let's just unlink this nonsense */
00558 
00559                      n=0;
00560               }
00561 
00562               if (n == 0 || n >= linked_name_len ||
00563                      (linked_name_buf[n]=0,
00564                      update_link(cur,
00565                             cur_base, linked_name_buf, shared, cur_name_ptr,
00566                             cur_name_len)))
00567               {
00568                      unlink(cur_base);
00569                      free(linked_name_buf);
00570                      free(cur_base);
00571                      free(cur_name_ptr);
00572                      closedir(dirp);
00573                      return (-1);
00574               }
00575               free(cur_base);
00576               free(linked_name_buf);
00577               free(cur_name_ptr);
00578        }
00579        if (dirp)     closedir(dirp);
00580        return (0);
00581 }
00582 
00583 /* Update the link pointer */
00584 
00585 static int update_link(const char *curdir,
00586        const char *linkname, const char *linkvalue,
00587        const char *shareddir,
00588        const char *msgfilename,
00589        size_t msgfilenamelen)
00590 {
00591        char   *p=malloc(strlen(shareddir)+sizeof("/cur/")+msgfilenamelen);
00592        char   *q;
00593        int    fd;
00594        struct maildir_tmpcreate_info createInfo;
00595 
00596        if (!p)
00597        {
00598               perror("malloc");
00599               return (-1);
00600        }
00601 
00602        strcat(strcpy(p, shareddir), "/cur/");
00603        q=p+strlen(p);
00604        memcpy(q, msgfilename, msgfilenamelen);
00605        q[msgfilenamelen]=0;
00606 
00607        if (linkvalue && strcmp(p, linkvalue) == 0)
00608        {
00609               /* the link is good */
00610 
00611               free(p);
00612               return (0);
00613        }
00614 
00615        /* Ok, we want this to be an atomic operation. */
00616 
00617        maildir_tmpcreate_init(&createInfo);
00618        createInfo.maildir=curdir;
00619        createInfo.uniq="relink";
00620        createInfo.doordie=1;
00621 
00622        if ((fd=maildir_tmpcreate_fd(&createInfo)) < 0)
00623               return -1;
00624 
00625        close(fd);
00626        unlink(createInfo.tmpname);
00627 
00628        if (symlink(p, createInfo.tmpname) < 0 ||
00629            rename(createInfo.tmpname, linkname) < 0)
00630        {
00631               perror(createInfo.tmpname);
00632               maildir_tmpcreate_free(&createInfo);
00633               return (-1);
00634        }
00635 
00636        maildir_tmpcreate_free(&createInfo);
00637        return (0);
00638 }
00639 
00640 /* and now, anything that's left in the temporary db must be new messages */
00641 
00642 static int newmsgs(const char *cur, const char *shared, struct dbobj *obj)
00643 {
00644        char   *key, *val;
00645        size_t keylen, vallen;
00646        int fd;
00647        struct maildir_tmpcreate_info createInfo;
00648 
00649        maildir_tmpcreate_init(&createInfo);
00650        createInfo.maildir=cur;
00651        createInfo.uniq="newlink";
00652        createInfo.doordie=1;
00653 
00654        if ((fd=maildir_tmpcreate_fd(&createInfo)) < 0)
00655               return -1;
00656        close(fd);
00657 
00658        unlink(createInfo.tmpname);
00659 
00660        for (key=dbobj_firstkey(obj, &keylen, &val, &vallen); key;
00661               key=dbobj_nextkey(obj, &keylen, &val, &vallen))
00662        {
00663        char   *slink=malloc(strlen(shared)+sizeof("/cur/")+vallen);
00664        char   *q;
00665 
00666               if (!slink)
00667               {
00668                      free(val);
00669                      maildir_tmpcreate_free(&createInfo);
00670                      return (-1);
00671               }
00672 
00673               strcat(strcpy(slink, shared), "/cur/");
00674               q=slink+strlen(slink);
00675               memcpy(q, val, vallen);
00676               q[vallen]=0;
00677               free(val);
00678 
00679               if (symlink(slink, createInfo.tmpname))
00680               {
00681                      perror(createInfo.tmpname);
00682 
00683                      free(slink);
00684                      maildir_tmpcreate_free(&createInfo);
00685                      return (-1);
00686               }
00687 
00688               free(slink);
00689               slink=malloc(strlen(cur)+sizeof("/new/" MDIRSEP "2,")+keylen);
00690               if (!slink)
00691               {
00692                      perror("malloc");
00693                      maildir_tmpcreate_free(&createInfo);
00694                      return (-1);
00695               }
00696 
00697               strcat(strcpy(slink, cur), "/new/");
00698               q=slink+strlen(slink);
00699               memcpy(q, key, keylen);
00700               strcpy(q+keylen, MDIRSEP "2,");
00701 
00702               if (rename(createInfo.tmpname, slink))
00703               {
00704                      free(slink);
00705                      maildir_tmpcreate_free(&createInfo);
00706                      return (-1);
00707               }
00708               free(slink);
00709        }
00710        maildir_tmpcreate_free(&createInfo);
00711        return (0);
00712 }
00713 
00714 static void do_maildir_shared_sync(const char *dir, const char *shared)
00715 {
00716 struct dbobj obj;
00717 char   *dbname;
00718 char   *cur;
00719 char   *shared_update_name;
00720 
00721 struct stat   stat1, stat2;
00722 int    fd;
00723 
00724        maildir_purgetmp(dir);      /* clean up after myself */
00725        maildir_getnew(dir, 0, NULL, NULL);
00726 
00727        maildir_purgetmp(shared);
00728        maildir_getnew(shared, 0, NULL, NULL);
00729 
00730        /* Figure out if we REALLY need to sync something */
00731 
00732        shared_update_name=malloc(strlen(dir)+sizeof("/shared-timestamp"));
00733        if (!shared_update_name)    return;
00734        strcat(strcpy(shared_update_name, dir), "/shared-timestamp");
00735        cur=malloc(strlen(shared)+sizeof("/new"));
00736        if (!cur)
00737        {
00738               free(shared_update_name);
00739               return;
00740        }
00741 
00742        if (stat(shared_update_name, &stat1) == 0)
00743        {
00744               if ( stat( strcat(strcpy(cur, shared), "/new"), &stat2) == 0 &&
00745                      stat2.st_mtime < stat1.st_mtime &&
00746                      stat( strcat(strcpy(cur, shared), "/cur"), &stat2)
00747                      == 0 && stat2.st_mtime < stat1.st_mtime)
00748               {
00749                      free(shared_update_name);
00750                      free(cur);
00751                      return;
00752               }
00753        }
00754        if ((fd=maildir_safeopen(shared_update_name, O_RDWR|O_CREAT, 0600))>= 0)
00755        {
00756               if (write(fd, "", 1) < 0)
00757                      perror("write");
00758               close(fd);
00759        }
00760 
00761        free(cur);
00762        free(shared_update_name);
00763 
00764        if (create_db(&obj, dir, &dbname)) return;
00765 
00766        if (build_db(shared, &obj))
00767        {
00768               dbobj_close(&obj);
00769               unlink(dbname);
00770               free(dbname);
00771               return;
00772        }
00773 
00774        if ((cur=malloc(strlen(dir)+sizeof("/cur"))) == 0)
00775        {
00776               perror("malloc");
00777               dbobj_close(&obj);
00778               unlink(dbname);
00779               free(dbname);
00780               return;
00781        }
00782        strcat(strcpy(cur, dir), "/cur");
00783        if (update_cur(cur, shared, &obj) == 0)
00784        {
00785               strcat(strcpy(cur, dir), "/new");
00786               if (update_cur(cur, shared, &obj) == 0)
00787               {
00788                      *strrchr(cur, '/')=0;       /* Chop off the /new */
00789                      newmsgs(cur, shared, &obj);
00790               }
00791        }
00792 
00793        free(cur);
00794        dbobj_close(&obj);
00795        unlink(dbname);
00796        free(dbname);
00797 }
00798 
00799 int maildir_sharedisro(const char *maildir)
00800 {
00801 char   *p=malloc(strlen(maildir)+sizeof("/shared/cur"));
00802 
00803        if (!p)
00804        {
00805               perror("malloc");
00806               return (-1);
00807        }
00808        strcat(strcpy(p, maildir), "/shared/cur");
00809 
00810        if (access(p, W_OK) == 0)
00811        {
00812               free(p);
00813               return (0);
00814        }
00815        free(p);
00816        return (1);
00817 }
00818 
00819 int maildir_unlinksharedmsg(const char *filename)
00820 {
00821 char   *buf=maildir_getlink(filename);
00822 
00823        if (buf)
00824        {
00825               struct stat stat_buf;
00826               int rc=unlink(buf);
00827 
00828               /*
00829               ** If we FAILED to unlink the real message in the real
00830               ** sharable folder, but the message still exists, it means
00831               ** that we do not have the permission to do so, so do not
00832               ** purge this folder.  Instead, remove the T flag from
00833               ** this message.
00834               */
00835 
00836               if (rc && stat(buf, &stat_buf) == 0)
00837               {
00838                      char *cpy=strdup(filename);
00839 
00840                      if (cpy)
00841                      {
00842                             char *p=strrchr(cpy, MDIRSEP[0]);
00843 
00844                             if (p && strchr(p, '/') == 0 &&
00845                                 strncmp(p, MDIRSEP "2,", 3) == 0 &&
00846                                 (p=strchr(p, 'T')) != 0)
00847                             {
00848                                    while ((*p=p[1]) != 0)
00849                                           ++p;
00850                                    rename(filename, cpy);
00851                             }
00852                             free(cpy);
00853                      }
00854                                           
00855                      free(buf);
00856                      return (0);
00857               }
00858               free(buf);
00859        }
00860        unlink(filename);
00861        return (0);
00862 }
00863 
00864 
00865 #else
00866 
00867 /* We cannot implement sharing */
00868 
00869 void maildir_list_sharable(const char *maildir,
00870        void (*func)(const char *, void *),
00871        void *voidp)
00872 {
00873 }
00874 
00875 int maildir_shared_subscribe(const char *maildir, const char *folder)
00876 {
00877        errno=EINVAL;
00878        return (-1);
00879 }
00880 
00881 void maildir_list_shared(const char *maildir,
00882        void (*func)(const char *, void *),
00883        void *voidp)
00884 {
00885 }
00886 
00887 int maildir_shared_unsubscribe(const char *maildir, const char *folder)
00888 {
00889        errno=EINVAL;
00890        return (-1);
00891 }
00892 
00893 #if 0
00894 char *maildir_shareddir(const char *maildir, const char *sharedname)
00895 {
00896        errno=EINVAL;
00897        return (0);
00898 }
00899 #endif
00900 
00901 void maildir_shared_sync(const char *maildir)
00902 {
00903 }
00904 
00905 int maildir_sharedisro(const char *maildir)
00906 {
00907        return (-1);
00908 }
00909 
00910 int maildir_unlinksharedmsg(const char *filename)
00911 {
00912        return (-1);
00913 }
00914 #endif