Logo Search packages:      
Sourcecode: maildrop version File versions  Download package

maildirquota.c

/*
** Copyright 1998 - 2003 Double Precision, Inc.
** See COPYING for distribution information.
*/

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <sys/types.h>
#if HAVE_DIRENT_H
#include <dirent.h>
#define NAMLEN(dirent) strlen((dirent)->d_name)
#else
#define dirent direct
#define NAMLEN(dirent) (dirent)->d_namlen
#if HAVE_SYS_NDIR_H
#include <sys/ndir.h>
#endif
#if HAVE_SYS_DIR_H
#include <sys/dir.h>
#endif
#if HAVE_NDIR_H
#include <ndir.h>
#endif
#endif
#include    <sys/types.h>
#if   HAVE_SYS_STAT_H
#include    <sys/stat.h>
#endif

#include    "maildirquota.h"
#include    "maildirmisc.h"
#include    "maildircreate.h"
#include    "quotawarnmsg.h"
#include    "../rfc822/rfc822.h"
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <errno.h>
#if   HAVE_FCNTL_H
#include    <fcntl.h>
#endif
#if   HAVE_UNISTD_H
#include    <unistd.h>
#endif
#include    <time.h>
#include    <numlib/numlib.h>

static const char rcsid[]="$Id: maildirquota.c,v 1.21 2003/02/13 03:19:45 mrsam Exp $";

static void parsequotastr(const char *, struct maildirquota *);

/* Read the maildirsize file */

static int maildir_openquotafile_init(struct maildirsize *info,
                              const char *maildir,
                              const char *newquota);

static int do_maildir_openquotafile(struct maildirsize *info,
                            const char *filename,
                            const char *newquota);

int maildir_openquotafile(struct maildirsize *info, const char *maildir)
{
      return (maildir_openquotafile_init(info, maildir, NULL));
}

static int maildir_openquotafile_init(struct maildirsize *info,
                              const char *maildir,
                              const char *newquota)
{
      int rc;

      char  *buf=(char *)malloc(strlen(maildir)+sizeof("/maildirfolder"));

      memset(info, 0, sizeof(*info));

      info->fd= -1;

      if (!buf)
            return (-1);

      strcat(strcpy(buf, maildir), "/maildirfolder");
      if (stat(buf, &info->statbuf) == 0) /* Go to parent */
      {
            strcat(strcpy(buf, maildir), "/..");

            rc=maildir_openquotafile_init(info, buf, newquota);
            free(buf);
            return rc;
      }

      info->maildir=strdup(maildir);

      if (!info->maildir)
      {
            free(buf);
            return (-1);
      }

      strcat(strcpy(info->maildirsizefile=buf, maildir), "/maildirsize");

      rc=do_maildir_openquotafile(info, buf, newquota);

      if (rc == 0)
            return (0);

      free(buf);
      free(info->maildir);
      return (rc);
}

static int do_maildir_openquotafile(struct maildirsize *info,
                            const char *filename,
                            const char *newquota)
{
      char buf[5120];
      char *p;
      unsigned l;
      int n;
      int first;

      /*
      ** When setting a new quota, we don't care about the existing
      ** maildirsize.
      */

      if ((info->fd=(newquota ? open("/dev/null", O_RDWR):
                   maildir_safeopen(filename,
                              O_RDWR|O_APPEND, 0))) < 0)
            return (0); /* No quota */

      if (newquota)
      {
            parsequotastr(newquota, &info->quota);

            if (info->quota.nbytes == 0 &&
                info->quota.nmessages == 0)
            {
                  close(info->fd);
                  info->fd= -1;
                  errno=EINVAL;
                  return (-1);
            }
            info->recalculation_needed=1;
            return (0);
      }

      p=buf;
      l=sizeof(buf);

      while (l)
      {
            n=read(info->fd, p, l);
            if (n < 0)
            {
                  close(info->fd);
                  info->fd= -1;
                  return (-1);
            }
            if (n == 0) break;
            p += n;
            l -= n;
      }

      if (fstat(info->fd, &info->statbuf))      /* maildir too big */
      {
            close(info->fd);
            info->fd= -1;
            return (-1);
      }

      if (l == 0) /*
                  ** maildirsize overflowed, still need to read its
                  ** quota
                  */
      {
            p[-1]=0;
            p=strchr(buf, '\n');
            if (p)
                  *p=0;
            parsequotastr(buf, &info->quota);
            info->recalculation_needed=1;
            return (0);
      }


      info->size.nbytes=0;
      info->size.nmessages=0;
      info->nlines=0;
      *p=0;
      p=buf;
      first=1;
      while (*p)
      {
            long n=0;
            int c=0;
            char  *q=p;
      
            while (*p)
                  if (*p++ == '\n')
                  {
                        p[-1]=0;
                        break;
                  }

            if (first)
            {
                  parsequotastr(q, &info->quota);
                  first=0;
                  continue;
            }
            sscanf(q, "%ld %d", &n, &c);
            info->size.nbytes += n;
            info->size.nmessages += c;
            ++ info->nlines;
      }
      return (0);
}

static void parsequotastr(const char *quota, struct maildirquota *q)
{
      off_t i;

      q->nbytes=0;
      q->nmessages=0;

      while (quota && *quota)
      {
            if (*quota < '0' || *quota > '9')
            {
                  ++quota;
                  continue;
            }
            i=0;
            while (*quota >= '0' && *quota <= '9')
                  i=i*10 + (*quota++ - '0');
            switch (*quota)   {
            case MDQUOTA_SIZE:
                  q->nbytes=i;
                  break;
            case MDQUOTA_COUNT:
                  q->nmessages=i;
                  break;
            }
      }
}


void maildir_closequotafile(struct maildirsize *info)
{
      if (info->maildir)
            free (info->maildir);
      info->maildir=NULL;

      if (info->maildirsizefile)
            free (info->maildirsizefile);
      info->maildirsizefile=NULL;

      if (info->fd >= 0)
            close(info->fd);
      info->fd= -1;
}

/**
 ** Check if size > quota, and calculate by how much
 */

static int checkOneQuota(off_t size, off_t quota, int *percentage);

static int checkQuota(struct maildirquota *size,
                  struct maildirquota *quota, int *percentage)
{
      int b_quota;
      int n_quota;

      if (checkOneQuota(size->nbytes, quota->nbytes, &b_quota) ||
          checkOneQuota(size->nmessages, quota->nmessages,
                    &n_quota))
      {
            if (percentage)
                  *percentage= 100;
            errno=ENOSPC;
            return -1;
      }

      if (b_quota < n_quota)
            b_quota=n_quota;

      if (percentage)
            *percentage=b_quota;
      return (0);
}

static int checkOneQuota(off_t size, off_t quota, int *percentage)
{
      int x=1;

      if (quota == 0) /* No quota */
      {
            *percentage=0;
            return (0);
      }

      if (size > quota)
      {
            *percentage=100;
            return (-1);
      }

      if (quota > 20000000)
            x=1024;

      *percentage= quota > 0 ? (size/x) * 100 / (quota/x):0;
      return 0;
}

static char *makenewmaildirsizename(const char *, int *);
static int countcurnew(const char *, time_t *, off_t *, unsigned *);
static int countsubdir(const char *, const char *,
            time_t *, off_t *, unsigned *);
static int statcurnew(const char *, time_t *);
static int statsubdir(const char *, const char *, time_t *);

static int  doaddquota(struct maildirsize *, int, long, int, int);

static int docheckquota(struct maildirsize *info,
                  long xtra_size,
                  int xtra_cnt, int *percentage);

int maildir_checkquota(struct maildirsize *info,
                   long xtra_size,
                   int xtra_cnt)
{
      int   dummy;

      return (docheckquota(info, xtra_size, xtra_cnt, &dummy));
}

int maildir_readquota(struct maildirsize *info)
{
      int   percentage=0;

      (void)docheckquota(info, 0, 0, &percentage);
      return (percentage);
}

static int docheckquota(struct maildirsize *info,
                  long xtra_size,
                  int xtra_cnt,
                  int *percentage)
{
      char  *newmaildirsizename;
      int   maildirsize_fd;
      off_t maildirsize_size;
      unsigned maildirsize_cnt;

      time_t      tm;
      time_t      maxtime;
      DIR   *dirp;
      struct dirent *de;

      struct maildirquota new_quota;

      *percentage=0;

      if (info->fd < 0) /* No quota */
            return (0);

      new_quota=info->size;

      new_quota.nbytes += xtra_size;
      new_quota.nmessages += xtra_cnt;

      if (!info->recalculation_needed &&
          checkQuota(&new_quota, &info->quota, percentage) == 0)
            return (0); /* New size is under quota */

      /*
      ** Overquota, see if it's time to recalculate the quota anyway
      */

      time(&tm);
      if (!info->recalculation_needed &&
          info->nlines == 1 && tm < info->statbuf.st_mtime + 15*60)
            return (-1);


      maxtime=0;
      maildirsize_size=0;
      maildirsize_cnt=0;

      if (countcurnew(info->maildir,
                  &maxtime, &maildirsize_size, &maildirsize_cnt))
      {
            errno=EIO;
            return (-1);
      }

      dirp=opendir(info->maildir);
      while (dirp && (de=readdir(dirp)) != 0)
      {
            if (countsubdir(info->maildir, de->d_name,
                        &maxtime, &maildirsize_size,
                  &maildirsize_cnt))
            {
                  errno=EIO;
                  closedir(dirp);
                  return (-1);
            }
      }
      if (dirp)
      {
#if   CLOSEDIR_VOID
            closedir(dirp);
#else
            if (closedir(dirp))
            {
                  errno=EIO;
                  return (-1);
            }
#endif
      }

      newmaildirsizename=makenewmaildirsizename(info->maildir,
                                      &maildirsize_fd);
      if (!newmaildirsizename)
      {
            errno=EIO;
            return (-1);
      }

      if (doaddquota(info, maildirsize_fd, maildirsize_size,
            maildirsize_cnt, 1))
      {
            free(newmaildirsizename);
            unlink(newmaildirsizename);
            close(maildirsize_fd);
            errno=EIO;
            return (-1);
      }

      if (rename(newmaildirsizename, info->maildirsizefile))
      {
            unlink(newmaildirsizename);
            close(maildirsize_fd);
            errno=EIO;
            return (-1);
      }

      info->recalculation_needed=0;
      info->size.nbytes=maildirsize_size;
      info->size.nmessages=maildirsize_cnt;
      info->nlines=1;
      close(info->fd);
      info->fd=maildirsize_fd;

      tm=0;

      if (statcurnew(info->maildir, &tm))
      {
            errno=EIO;
            return (-1);
      }

      dirp=opendir(info->maildir);
      while (dirp && (de=readdir(dirp)) != 0)
      {
            if (statsubdir(info->maildir, de->d_name, &tm))
            {
                  errno=EIO;
                  closedir(dirp);
                  return (-1);
            }
      }
      if (dirp)
      {
#if   CLOSEDIR_VOID
            closedir(dirp);
#else
            if (closedir(dirp))
            {
                  errno=EIO;
                  return (-1);
            }
#endif
      }

      if (tm != maxtime)      /* Race condition, someone changed something */
      {
            info->recalculation_needed=1;
            info->nlines=0;
            errno=EAGAIN;
            return (-1);
      }

      *percentage=0;

      new_quota=info->size;

      new_quota.nbytes += xtra_size;
      new_quota.nmessages += xtra_cnt;

      return checkQuota(&new_quota, &info->quota, percentage);
}

int   maildir_addquota(struct maildirsize *info,
                   long maildirsize_size, int maildirsize_cnt)
{
      if (info->fd < 0)
            return (0);

      return (doaddquota(info, info->fd, maildirsize_size,
                     maildirsize_cnt, 0));
}

static int doaddquota(struct maildirsize *info, int maildirsize_fd,
                  long maildirsize_size, int maildirsize_cnt,
                  int isnew)
{
      char  n[NUMBUFSIZE];
      char  buf[NUMBUFSIZE * 4 + 32 ];
      char *p;
      int cnt;

      buf[0]=0;

      if (isnew)
      {
            if (info->quota.nbytes > 0)
            {
                  char b[2];

                  b[0]=MDQUOTA_SIZE;
                  b[1]=0;

                  strcat(strcat(buf, libmail_str_off_t(info->quota.nbytes, n)),
                         b);
            }

            if (info->quota.nmessages > 0)
            {
                  char b[2];

                  b[0]=MDQUOTA_COUNT;
                  b[1]=0;

                  if (buf[0] != 0)
                        strcat(buf, ",");

                  strcat(strcat(buf,
                              libmail_str_size_t(info->quota.nmessages, n)),
                         b);
            }
            strcat(buf, "\n");
      }

      sprintf(buf + strlen(buf),
            "%8s ", libmail_str_off_t(maildirsize_size, n));

      sprintf(buf + strlen(buf),
            "%4s\n", libmail_str_off_t(maildirsize_cnt, n));

      p=buf;
      cnt=strlen(buf);

      while (cnt > 0)
      {
            int c=write( maildirsize_fd, p, cnt);

            if (c < 0)
                  return (-1);

            cnt -= c;
            p += c;
      }

      return (0);
}


/* New maildirsize is built in the tmp subdirectory */

static char *makenewmaildirsizename(const char *dir, int *fd)
{
char  hostname[256];
struct      stat stat_buf;
time_t      t;
char  *p;

      hostname[0]=0;
      hostname[sizeof(hostname)-1]=0;
      gethostname(hostname, sizeof(hostname)-1);
      p=(char *)malloc(strlen(dir)+strlen(hostname)+130);
      if (!p)     return (0);

      for (;;)
      {
      char  tbuf[NUMBUFSIZE];
      char  pbuf[NUMBUFSIZE];

            time(&t);
            strcat(strcpy(p, dir), "/tmp/");
            sprintf(p+strlen(p), "%s.%s_NeWmAiLdIrSiZe.%s",
                  libmail_str_time_t(t, tbuf),
                  libmail_str_pid_t(getpid(), pbuf), hostname);

            if (stat( (const char *)p, &stat_buf) < 0 &&
                  (*fd=maildir_safeopen(p,
                        O_CREAT|O_RDWR|O_APPEND, 0644)) >= 0)
                  break;
            sleep(3);
      }
      return (p);
}

static int statcurnew(const char *dir, time_t *maxtimestamp)
{
char  *p=(char *)malloc(strlen(dir)+5);
struct      stat  stat_buf;

      if (!p)     return (-1);
      strcat(strcpy(p, dir), "/cur");
      if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
            *maxtimestamp=stat_buf.st_mtime;
      strcat(strcpy(p, dir), "/new");
      if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
            *maxtimestamp=stat_buf.st_mtime;
      free(p);
      return (0);
}

static int statsubdir(const char *dir, const char *subdir, time_t *maxtime)
{
char  *p;
int   n;

      if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
            strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
            return (0);

      p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
      if (!p)     return (-1);
      strcat(strcat(strcpy(p, dir), "/"), subdir);
      n=statcurnew(p, maxtime);
      free(p);
      return (n);
}

static int docount(const char *, time_t *, off_t *, unsigned *);

static int countcurnew(const char *dir, time_t *maxtime,
      off_t *sizep, unsigned *cntp)
{
char  *p=(char *)malloc(strlen(dir)+5);
int   n;

      if (!p)     return (-1);
      strcat(strcpy(p, dir), "/new");
      n=docount(p, maxtime, sizep, cntp);
      if (n == 0)
      {
            strcat(strcpy(p, dir), "/cur");
            n=docount(p, maxtime, sizep, cntp);
      }
      free(p);
      return (n);
}

static int countsubdir(const char *dir, const char *subdir, time_t *maxtime,
      off_t *sizep, unsigned *cntp)
{
char  *p;
int   n;

      if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
           strcmp(subdir, "..") == 0 ||
           ! maildirquota_countfolder(subdir))
            return (0);

      p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
      if (!p)     return (2);
      strcat(strcat(strcpy(p, dir), "/"), subdir);
      n=countcurnew(p, maxtime, sizep, cntp);
      free(p);
      return (n);
}

static int docount(const char *dir, time_t *dirstamp,
      off_t *sizep, unsigned *cntp)
{
struct      stat  stat_buf;
char  *p;
DIR   *dirp;
struct dirent *de;
unsigned long     s;

      if (stat(dir, &stat_buf))     return (0); /* Ignore */
      if (stat_buf.st_mtime > *dirstamp)  *dirstamp=stat_buf.st_mtime;
      if ((dirp=opendir(dir)) == 0) return (0);
      while ((de=readdir(dirp)) != 0)
      {
      const char *n=de->d_name;

            if (*n == '.')    continue;

            if (!maildirquota_countfile(n))
                  continue;

            if (maildir_parsequota(n, &s) == 0)
                  stat_buf.st_size=s;
            else
            {
                  p=(char *)malloc(strlen(dir)+strlen(n)+2);
                  if (!p)
                  {
                        closedir(dirp);
                        return (-1);
                  }
                  strcat(strcat(strcpy(p, dir), "/"), n);
                  if (stat(p, &stat_buf))
                  {
                        free(p);
                        continue;
                  }
                  free(p);
            }
            *sizep += stat_buf.st_size;
            ++*cntp;
      }

#if   CLOSEDIR_VOID
      closedir(dirp);
#else
      if (closedir(dirp))
            return (-1);
#endif
      return (0);
}

int maildirquota_countfolder(const char *folder)
{
#ifdef TRASHQUOTA

#else

      if (strcmp(folder, "." TRASH) == 0 ||
          strcmp(folder, "." TRASH "/") == 0)
            return (0);

      for ( ; *folder; folder++)
            if (*folder == '/' &&
                (strcmp(folder+1, "." TRASH) == 0 ||
                 strcmp(folder+1, "." TRASH "/") == 0))
                  return (0);
#endif
      return (1);
}

int maildirquota_countfile(const char *n)
{
#ifdef TRASHQUOTA

#else
      const char *nn=strrchr(n, '/');

      if (nn != NULL)
            n=nn+1;

      /* do not count msgs marked as deleted */

      for ( ; *n; n++)
      {
            if (n[0] != MDIRSEP[0] || n[1] != '2' ||
                n[2] != ',')  continue;
            n += 3;
            while (*n >= 'A' && *n <= 'Z')
            {
                  if (*n == 'T')    return (0);
                  ++n;
            }
            break;
      }
#endif
      return (1);
}

/*
** Prepare to add something to the maildir
*/

int maildir_quota_add_start(const char *maildir,
                      struct maildirsize *info,
                      long msgsize, int nmsgs,
                      const char *newquota)
{
      struct maildirquota mq;
      int i;

      if ( maildir_openquotafile(info, maildir))
            info->fd= -1;

      if (newquota != NULL)
      {
            parsequotastr(newquota, &mq);

            if ((mq.nbytes > 0 || mq.nmessages > 0) &&
                (info->fd < 0 || info->quota.nbytes != mq.nbytes ||
                 info->quota.nmessages != mq.nmessages))
            {
                  if (info->fd < 0)
                  {
                        maildir_quota_set(maildir, newquota);
                        if (maildir_openquotafile(info, maildir))
                              info->fd= -1;
                  }
                  else
                  {
                        info->quota=mq;
                        info->recalculation_needed=1;
                  }
            }
      }
      if (info->fd < 0)
            return (0); /* No quota set on this maildir */

      for (i=0; i<5; i++)
      {
            int rc;

            rc=maildir_checkquota(info, msgsize, nmsgs);
            if (rc == 0)
                  return (0);

            if (errno != EAGAIN)
            {
                  maildir_closequotafile(info);
                  return (-1);
            }
      }
      maildir_closequotafile(info);

      /* Cannot recover from a race condition, just punt */

      return (0);
}

void maildir_quota_add_end(struct maildirsize *info,
                     long msgsize, int nmsgs)
{
      maildir_addquota(info, msgsize, nmsgs);
      maildir_closequotafile(info);
}

void maildir_quota_deleted(const char *maildir,
                     long nbytes,   /* Must be negative */
                     int nmsgs)     /* Must be negative */
{
      struct maildirsize info;

      if ( maildir_openquotafile(&info, maildir))
            return;

      maildir_checkquota(&info, nbytes, nmsgs); /* Cleanup */
      maildir_addquota(&info, nbytes, nmsgs);
      maildir_closequotafile(&info);
}

void maildir_quota_recalculate(const char *maildir)
{
      struct maildirsize info;

      if (maildir_openquotafile(&info, maildir))
            return;
      info.recalculation_needed=1;

      maildir_readquota(&info);
      maildir_closequotafile(&info);
}

int maildir_quota_delundel_start(const char *maildir,
                         struct maildirsize *info,
                         long msgsize, int nmsgs)
{
#if TRASHQUOTA
      return (0);
#else
      if (nmsgs < 0)
      {
            maildir_quota_deleted(maildir, msgsize, nmsgs);
            return (0); /* Always allowed */
      }

      return maildir_quota_add_start(maildir, info, msgsize, nmsgs, NULL);
#endif
}

void maildir_quota_delundel_end(struct maildirsize *info,
                        long msgsize, int nmsgs)
{
#if TRASHQUOTA
      return;
#else
      if (nmsgs < 0)
            return;

      maildir_quota_add_end(info, msgsize, nmsgs);
#endif
}


void maildir_quota_set(const char *dir, const char *quota)
{
      struct maildirsize info;

      if (maildir_openquotafile_init(&info, dir, quota) == 0)
      {
            maildir_checkquota(&info, 0, 0);
            maildir_closequotafile(&info);
      }
}


static void do_deliver_warning(const char *msgfile, const char *dir)
{
int   fdin, fd;
FILE *fpout;
time_t      t;
size_t      l, msg_len;
char  *qname = 0;
struct stat sb;
char  hostname[256];
char  buf[4096];
size_t      n;
struct      maildirsize info;
struct maildir_tmpcreate_info createInfo;

      if ((fdin=open(msgfile, O_RDONLY)) < 0)
            return;

      l = strlen(dir)+sizeof("/quotawarn");

      /* Send only one warning every 24 hours */
      if ((qname = malloc(l)) == 0)
      {
            close(fdin);
            return;
      }

      strcat(strcpy(qname, dir), "/quotawarn");
      time(&t);
      if (stat(qname, &sb) == 0 && ((sb.st_mtime + 86400) > t))
      {
            free(qname);
            close(fdin);
            return;
      }

      fd = open(qname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
      free(qname);
      if (!fd)
      {
            close(fdin);
            return;
      }
      write(fd, buf, 0);
      close(fd);

      strcpy(buf, "Date: ");
      rfc822_mkdate_buf(t, buf+strlen(buf));
      strcat(buf, "\n");

      hostname[0]=0;
      hostname[sizeof(hostname)-1]=0;
      gethostname(hostname, sizeof(hostname)-1);
      sprintf(buf, "%sMessage-Id: <%lu.overquota@%-1.256s>\n",
            buf, (unsigned long)t, hostname);

      if (stat(msgfile, &sb) < 0) {
            close(fdin);
            return;
      }
      msg_len=strlen(buf)+sb.st_size;



      maildir_tmpcreate_init(&createInfo);
      createInfo.maildir=dir;
      createInfo.uniq="warn";
      createInfo.msgsize=msg_len;
      createInfo.doordie=1;

      if ((fpout=maildir_tmpcreate_fp(&createInfo)) == NULL)
      {
            close(fdin);
            return;
      }

      fprintf(fpout, "%s", buf);

      while ((n=read(fdin, buf, sizeof(buf))) > 0)
      {
            fwrite(buf, n, 1, fpout);
      }
      close(fdin);

      if (fflush(fpout) || ferror(fpout))
      {
            fclose(fpout);
            unlink(createInfo.tmpname);
            maildir_tmpcreate_free(&createInfo);
            return;
      }

      if (fseek(fpout, 0L, SEEK_SET) >= 0)
      {
            /* Make sure the quota message's size itself is factored into
            ** the quota. Deliver the message regardless of whether the
            ** user is over quota.
            */
            if (maildirquota_countfolder(dir))
            {
                  maildir_quota_add_start(dir, &info, msg_len, 1, NULL);
                  maildir_quota_add_end(&info, msg_len, 1);
            }
      }

      fclose(fpout);
      if (maildir_movetmpnew(createInfo.tmpname,
                         createInfo.newname))
      {
            unlink(createInfo.tmpname);
            maildir_tmpcreate_free(&createInfo);
            return;
      }
      maildir_tmpcreate_free(&createInfo);
}

void maildir_deliver_quota_warning(const char *dir, const int percent)
{
      size_t l;
      char *p;
      struct stat sb;

      /* If we delivered to a folder, dump the warning message into INBOX */

      l = strlen(dir)+sizeof("/maildirfolder");
      if ((p = malloc(l)) == 0)
            return;

      strcat(strcpy(p, dir), "/maildirfolder");

      /* If delivering to a folder, find quotawarn in its parent directory */

      if (stat(p, &sb) == 0)
      {
            strcat(strcpy(p, dir), "/..");
            maildir_deliver_quota_warning(p, percent);
            free(p);
            return;
      }
      free(p);

      if (percent >= 0)
      {
            struct maildirsize info;

            if (maildir_openquotafile(&info, dir) == 0)
            {
                  if (maildir_readquota(&info) >= percent)
                  {
                        maildir_closequotafile(&info);
                        do_deliver_warning(QUOTAWARNMSG, dir);
                        return;
                  }
                  maildir_closequotafile(&info);
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index