Back to index

courier  0.68.2
Classes | Defines | Functions
pcpdir.c File Reference
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <rfc822/rfc822hdr.h>
#include "pcp.h"

Go to the source code of this file.

Classes

struct  PCPdir
struct  PCPdir_event_participant
struct  PCPdir_new_eventid
struct  line_buffer
struct  cleanup_filename_list

Defines

#define dirent   direct
#define HOSTNAMELEN   256
#define TRY_SLEEP   3
#define TRY_MAX   3
#define TIME_FIELD   "t" /* start,end */
#define CANCELLED_FIELD   "c" /* This event has been cancelled */
#define BOOKED_FIELD   "b" /* This is a booked event */
#define PENDEL_FIELD   "d" /* This event is pending to be deleted */
#define PROXY_FIELD   "P" /* This event was placed by proxy */
#define PARTICIPANT_FIELD   "p" /* event participant */

Functions

static void pcp_close_dir (struct PCPdir *)
static int cleanup (struct PCPdir *)
static struct PCPdir_new_eventidneweventid (struct PCPdir *, const char *, struct PCP_save_event *)
static void destroyeventid (struct PCPdir *, struct PCPdir_new_eventid *)
static int saveevent (struct PCPdir *, struct PCPdir_new_eventid *, struct PCP_save_event *)
static int commitevent (struct PCPdir *, struct PCPdir_new_eventid *, struct PCP_commit *)
static int bookevent (struct PCPdir *, struct PCPdir_new_eventid *, struct PCP_commit *)
static int listallevents (struct PCPdir *, struct PCP_list_all *)
static int cancelevent (struct PCPdir *, const char *, int *)
static int uncancelevent (struct PCPdir *, const char *, int, struct PCP_uncancel *)
static int deleteevent (struct PCPdir *, struct PCP_delete *)
static int retrevent (struct PCPdir *, struct PCP_retr *)
static int setacl (struct PCPdir *, const char *, int)
static int listacl (struct PCPdir *, int(*)(const char *, int, void *), void *)
static const char * errmsg (struct PCP *pcp)
static void noop (struct PCP *pcp)
static const char * getauthtoken (struct PCP *pcp)
struct PCPpcp_open_dir (const char *dirname, const char *username)
static void mkunique (struct PCPdir *pd)
static char * dotlockname (struct PCPdir *pd)
static char * changedname (struct PCPdir *pd)
static void markchanged (struct PCPdir *pd)
static int kill_stale_lock (struct PCPdir *pd, const char *stale_lock, time_t *tm)
static char * acquire_dotlock (struct PCPdir *pd)
static void release_dotlock (struct PCPdir *pd, char *n)
static int lb_init (struct line_buffer *pi)
static void lb_destroy (struct line_buffer *pi)
static int lb_read (FILE *fp, struct line_buffer *pi)
static int lb_is_eventid (struct line_buffer *pi, const char *ei)
static char * lb_event_id (struct line_buffer *pi)
static char * lb_filename (struct PCPdir *pd, struct line_buffer *pi)
static char * lb_filename_nodir (struct line_buffer *pi)
static const char * lb_first_field (struct line_buffer *pi)
static const char * lb_next_field (struct line_buffer *pi)
static int lb_is_field (const char *p, const char *n)
static int lb_is_cancelled (struct line_buffer *pi)
static int lb_is_proxy (struct line_buffer *pi)
static const char * lb_field_value (const char *p)
static int lb_is_booked (struct line_buffer *pi, time_t *t)
static char * lb_field_value_buf (const char *p)
static const char * lb_is_pendel (struct line_buffer *pi)
static int lb_remove_field (struct line_buffer *pi, FILE *nfp, const char *fieldname, const char *newfield, const char *newvalue)
static int docommitevent (struct PCPdir *, struct PCPdir_new_eventid *, int, struct PCP_commit *)
static int pcp_is_conflict (struct line_buffer *, const struct PCP_event_time **, unsigned, struct PCP_commit *, struct PCP_uncancel *)
static int eventexists (struct PCPdir *pd, const char *e, int *flag)
static int event_expired (struct line_buffer *, time_t)
static int parse_time_field (const char *, time_t *, time_t *)
static int read_event_times (struct line_buffer *pi, struct PCP_event_time **time_ret, unsigned *time_n_ret)
static int retrheaders (struct PCPdir *, struct PCP_retr *, const char *)
static int retrrfc822 (struct PCPdir *, struct PCP_retr *, const char *)

Class Documentation

struct PCPdir

Definition at line 41 of file pcpdir.c.

Class Members
char * dirname
char hostname_buf
char * indexname
char * newindexname
unsigned uniq_cnt
char unique_filename_buf
char * username
struct PCPdir_event_participant

Definition at line 52 of file pcpdir.c.

Class Members
char * address
char * eventid
struct PCPdir_new_eventid

Definition at line 57 of file pcpdir.c.

Collaboration diagram for PCPdir_new_eventid:
Class Members
int booked
struct PCPdir_event_participant * event_participants
unsigned n_event_participants
char * newfile
char * oldeventid
char * tmpfile
struct line_buffer

Definition at line 834 of file pcpdir.c.

Class Members
char * buffer
int bufsiz
char * next_field
struct cleanup_filename_list

Definition at line 1501 of file pcpdir.c.

Collaboration diagram for cleanup_filename_list:
Class Members
char * filename
struct cleanup_filename_list * next

Define Documentation

#define BOOKED_FIELD   "b" /* This is a booked event */

Definition at line 827 of file pcpdir.c.

#define CANCELLED_FIELD   "c" /* This event has been cancelled */

Definition at line 826 of file pcpdir.c.

#define dirent   direct

Definition at line 25 of file pcpdir.c.

#define HOSTNAMELEN   256

Definition at line 39 of file pcpdir.c.

#define PARTICIPANT_FIELD   "p" /* event participant */

Definition at line 830 of file pcpdir.c.

#define PENDEL_FIELD   "d" /* This event is pending to be deleted */

Definition at line 828 of file pcpdir.c.

#define PROXY_FIELD   "P" /* This event was placed by proxy */

Definition at line 829 of file pcpdir.c.

#define TIME_FIELD   "t" /* start,end */

Definition at line 825 of file pcpdir.c.

#define TRY_MAX   3

Definition at line 297 of file pcpdir.c.

#define TRY_SLEEP   3

Definition at line 296 of file pcpdir.c.


Function Documentation

static char* acquire_dotlock ( struct PCPdir pd) [static]

Definition at line 385 of file pcpdir.c.

{
       char *n=dotlockname(pd);
       char *tmpname;
       FILE *fp;
       unsigned try_cnt;
       time_t last_time;

       if (!n)
              return (NULL);

       mkunique(pd);

       tmpname=malloc(strlen(pd->dirname)+strlen(pd->unique_filename_buf)
                     +20);

       if (!tmpname)
       {
              free(n);
              fprintf(stderr, "ALERT: Failed to create dotlock: %s - %s\n",
                     n, strerror(errno));
              return (NULL);
       }
       strcat(strcat(strcat(strcpy(tmpname, pd->dirname), "/."),
                    pd->unique_filename_buf), ".lock");

       fp=fopen(tmpname, "w");

       if (!fp)
       {
              free(tmpname);
              free(n);
              fprintf(stderr, "ALERT: Failed to create dotlock: %s - %s\n",
                     n, strerror(errno));
              return (NULL);
       }

       if (fprintf(fp, "%lu %s\n", (unsigned long)getpid(), pd->hostname_buf)
           < 0 || fflush(fp))
       {
              fclose(fp);
              unlink(tmpname);
              free(tmpname);
              free(n);
              fprintf(stderr, "ALERT: Failed to create dotlock: %s - %s\n",
                     n, strerror(errno));
              return (NULL);
       }

       if (fclose(fp) < 0)
       {
              unlink(tmpname);
              free(tmpname);
              free(n);
              fprintf(stderr, "ALERT: Failed to create dotlock: %s - %s\n",
                     n, strerror(errno));
              return (NULL);
       }

       try_cnt=0;
       last_time=0;
       for (;;)
       {
              time_t timestamp;
              int rc=kill_stale_lock(pd, n, &timestamp);

              if (rc > 0)
              {
                     ++try_cnt;
                     if (last_time == 0)
                            last_time=timestamp;

                     if (timestamp != last_time)
                            try_cnt=0;    /* Dot-lock was modified,
                                          ** reset.
                                          */

                     if (try_cnt == TRY_MAX)     /* Time to kill dot lock */
                     {
                            if (rc > 1 || (unlink(n) < 0
                                          && errno != ENOENT))
                            {
                                   fprintf(stderr, "ALERT: "
                                          "Failed to obtain dotlock: %s\n",
                                          n);

                                   unlink(tmpname);
                                   free(tmpname);
                                   free(n);
                                   return (NULL);
                            }
                            fprintf(stderr, "ALERT: Removed stale dotlock: %s\n",
                                   n);

                     }
                     else if (try_cnt > TRY_MAX)
                     {
                            fprintf(stderr, "ALERT: "
                                   "Failed to obtain dotlock: %s\n",
                                   n);

                            unlink(tmpname);
                            free(tmpname);
                            free(n);
                            return (NULL);
                     }
                     last_time=timestamp;
                     sleep(TRY_SLEEP);
                     continue;
              }

              if (rc < 0)
              {
                     fprintf(stderr, "ALERT: Failed to obtain dotlock: %s\n",
                            n);
                     unlink(tmpname);
                     free(tmpname);
                     free(n);
                     return (NULL);
              }

              if (link(tmpname, n) == 0)
                     break;

              if (try_cnt > TRY_MAX)
              {
                     fprintf(stderr, "ALERT: Failed to obtain dotlock: %s\n",
                            n);

                     unlink(tmpname);
                     free(tmpname);
                     free(n);
                     return (NULL);
              }
              ++try_cnt;
              sleep(TRY_SLEEP);
       }

       unlink(tmpname);
       free(tmpname);
       return (n);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int bookevent ( struct PCPdir pd,
struct PCPdir_new_eventid ae,
struct PCP_commit ci 
) [static]

Definition at line 1138 of file pcpdir.c.

{
       return (docommitevent(pd, ae, 1, ci));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cancelevent ( struct PCPdir pd,
const char *  event,
int *  errcode 
) [static]

Definition at line 1931 of file pcpdir.c.

{
       char *dotlock;
       FILE *fp;
       FILE *nfp;
       int rc;
       int found=0;

       if (errcode) *errcode=0;
       dotlock=acquire_dotlock(pd);

       if (!dotlock)
              return (-1);

       rc= -1;
       fp=fopen(pd->indexname, "a+");
       if (fp && fseek(fp, 0L, SEEK_SET) >= 0)
       {
              nfp=fopen(pd->newindexname, "w");
              if (nfp)
              {
                     struct line_buffer pi;

                     if (lb_init(&pi) == 0)
                     {
                            rc= 0;
                            while (lb_read(fp, &pi) == 0)
                            {
                                   if (!lb_is_eventid(&pi, event))
                                   {
                                          fprintf(nfp, "%s\n",
                                                 pi.buffer);
                                          continue;
                                   }
                                   found=1;
                                   if (lb_is_cancelled(&pi))
                                   {
                                          /* Already canned */
                                          fprintf(nfp, "%s\n",
                                                 pi.buffer);
                                          continue;
                                   }

                                   fprintf(nfp, "%s\t"
                                          CANCELLED_FIELD
                                          "\n", pi.buffer);
                            }
                            lb_destroy(&pi);
                            if (!found)
                            {
                                   if (errcode)
                                          *errcode=PCP_ERR_EVENTNOTFOUND;
                                   errno=ENOENT;
                                   rc= -1;
                            }
                     }
                     if (ferror(nfp) || fflush(nfp))
                            rc= -1;
                     if (fclose(nfp))
                            rc= -1;
              }
              fclose(fp);

              if (rc == 0 && rename(pd->newindexname, pd->indexname))
                     rc= -1;
       }
       else if (fp)
              fclose(fp);
       release_dotlock(pd, dotlock);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* changedname ( struct PCPdir pd) [static]

Definition at line 262 of file pcpdir.c.

{
       char *p=malloc(strlen(pd->dirname)+sizeof("/changed"));

       if (!p)
       {
              fprintf(stderr, "CRIT: out of memory.\n");
              return (NULL);
       }

       return (strcat(strcpy(p, pd->dirname), "/changed"));
}

Here is the caller graph for this function:

static int cleanup ( struct PCPdir pd) [static]

Definition at line 1508 of file pcpdir.c.

{
       char *dotlock;
       FILE *fp;
       FILE *nfp;
       int rc;
       struct stat stat_buf;
       struct cleanup_filename_list *list=NULL;
       time_t now;

       dotlock=acquire_dotlock(pd);

       if (!dotlock)
              return (-1);

       /*
       ** Read the current index.
       ** Remove entries for events whose files don't exist.
       **
       ** Save list of all files that are indexed.
       */

       time(&now);
       rc= -1;
       fp=fopen(pd->indexname, "a+");
       if (fp && fseek(fp, 0L, SEEK_SET) >= 0)
       {
              nfp=fopen(pd->newindexname, "w");
              if (nfp)
              {
                     struct line_buffer pi;

                     if (lb_init(&pi) == 0)
                     {
                            rc= 0;
                            while (lb_read(fp, &pi) == 0)
                            {
                                   char *filename=lb_filename(pd, &pi);
                                   struct cleanup_filename_list *l;
                                   time_t booked_time;

                                   if (!filename)
                                   {
                                          rc= -1;
                                          break;
                                   }

                                   if (!*filename)
                                   {
                                          free(filename);
                                          continue;
                                   }

                                   if (lb_is_booked(&pi, &booked_time))
                                   {
                                          /* Expire books after 1 hr */

                                          if (booked_time < now - 60*60)
                                          {
                                                 free(filename);
                                                 continue;
                                          }
                                   }
                                   else if (stat(filename, &stat_buf))
                                   {
                                          if (errno != ENOENT)
                                          {
                                                 free(filename);
                                                 rc= -1;
                                                 break;
                                          }
                                          free(filename);
                                          continue;
                                   }
                                   else if ( event_expired(&pi,
                                                        now -
                                                        CALENDARPURGE *
                                                        60 * 60 * 24))
                                   {
                                          free(filename);
                                          continue;
                                          /*
                                          ** cleanup loop below will
                                          ** take care of the event file
                                          */
                                   }

                                   l=malloc(sizeof(*list));
                                   l->next=list;
                                   l->filename=filename;
                                   list=l;

                                   fprintf(nfp, "%s\n", pi.buffer);
                            }
                            lb_destroy(&pi);
                     }

                     if (rc == 0 && (ferror(fp) || ferror(nfp)
                                   || fflush(nfp)))
                            rc= -1;

                     if (fclose(nfp))
                            rc= -1;
              }
              if (fclose(fp))
                     rc= -1;

              if (rename(pd->newindexname, pd->indexname))
                     rc= -1;
       }
       else if (fp)
              fclose(fp);

       if (rc == 0)  /* Time to scan the directory */
       {
              DIR *dirp=opendir(pd->dirname);
              struct dirent *de;
              const char *p;
              time_t now;

              time(&now);

              while (dirp && (de=readdir(dirp)) != NULL)
              {
                     char *filename=malloc(strlen(pd->dirname)+2+
                                         strlen(de->d_name));
                     if (!filename)
                     {
                            rc= -1;
                            break;
                     }
                     strcat(strcat(strcpy(filename, pd->dirname),
                                  "/"), de->d_name);
                     if (isdigit((int)(unsigned char)de->d_name[0]))
                     {
                            struct cleanup_filename_list *l;
                            for (l=list; l; l=l->next)
                                   if (strcmp(l->filename, filename) == 0)
                                          break;

                            if (!l)
                            {
                                   unlink(filename);
                            }
                     }
                     else
                     {
                            p=strrchr(filename, '.');
                            if (p && (strcmp(p, ".tmp") == 0 ||
                                     strcmp(p, ".lock") == 0) &&
                                stat(filename, &stat_buf) == 0 &&
                                stat_buf.st_mtime < now - 36 * 60 * 60)
                                   unlink(filename);
                     }
                     free(filename);
              }
              if (dirp)
                     closedir(dirp);
       }
       release_dotlock(pd, dotlock);

       while (list)
       {
              struct cleanup_filename_list *l=list;

              list=l->next;
              free(l->filename);
              free(l);
       }
       return (rc);
}

Here is the call graph for this function:

static int commitevent ( struct PCPdir pd,
struct PCPdir_new_eventid ae,
struct PCP_commit ci 
) [static]

Definition at line 1132 of file pcpdir.c.

{
       return (docommitevent(pd, ae, 0, ci));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int deleteevent ( struct PCPdir pd,
struct PCP_delete del 
) [static]

Definition at line 2135 of file pcpdir.c.

{
       char *dotlock;
       FILE *fp;
       FILE *nfp;
       int rc;
       char *deleted_event=0;

       del->errcode=0;
       dotlock=acquire_dotlock(pd);

       if (!dotlock)
              return (-1);

       rc= -1;
       fp=fopen(pd->indexname, "a+");
       if (fp && fseek(fp, 0L, SEEK_SET) >= 0)
       {
              nfp=fopen(pd->newindexname, "w");
              if (nfp)
              {
                     struct line_buffer pi;

                     if (lb_init(&pi) == 0)
                     {
                            rc= 0;
                            while (lb_read(fp, &pi) == 0)
                            {
                                   if (!lb_is_eventid(&pi, del->id))
                                   {
                                          fprintf(nfp, "%s\n",
                                                 pi.buffer);
                                          continue;
                                   }

                                   if (deleted_event) /* ??? */
                                          free(deleted_event);
                                   deleted_event=lb_filename(pd, &pi);
                                   if (!deleted_event)
                                          rc= -1;
                            }
                            lb_destroy(&pi);
                            if (!deleted_event)
                            {
                                   del->errcode=PCP_ERR_EVENTNOTFOUND;
                                   errno=ENOENT;
                                   rc= -1;
                            }
                     }
                     if (ferror(nfp) || fflush(nfp))
                            rc= -1;
                     if (fclose(nfp))
                            rc= -1;
              }
              fclose(fp);

              if (rc == 0 && rename(pd->newindexname, pd->indexname))
                     rc= -1;
       }
       else if (fp)
              fclose(fp);
       if (deleted_event && rc == 0)
              unlink(deleted_event);
       if (deleted_event)
              free(deleted_event);
       markchanged(pd);
       release_dotlock(pd, dotlock);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void destroyeventid ( struct PCPdir pd,
struct PCPdir_new_eventid p 
) [static]

Definition at line 745 of file pcpdir.c.

{
       unsigned i;

       for (i=0; i<p->n_event_participants; i++)
       {
              if (p->event_participants[i].eventid)
                     free(p->event_participants[i].eventid);
              if (p->event_participants[i].address)
                     free(p->event_participants[i].address);
       }
       if (p->event_participants)
              free(p->event_participants);

       if (p->booked && p->eventid.eventid)
       {
              struct PCP_delete del;

              memset(&del, 0, sizeof(del));
              del.id=p->eventid.eventid;

              deleteevent(pd, &del);
       }

       if (p->oldeventid)
              free(p->oldeventid);
       free(p->newfile);

       if (p->tmpfile)
       {
              unlink(p->tmpfile);
              free(p->tmpfile);
              p->tmpfile=NULL;
       }

       free(p->eventid.eventid);
       free(p);
}             

Here is the call graph for this function:

Here is the caller graph for this function:

static int docommitevent ( struct PCPdir pd,
struct PCPdir_new_eventid ae,
int  bookmode,
struct PCP_commit ci 
) [static]

Definition at line 1190 of file pcpdir.c.

{
       const struct PCP_event_time **times;
       char *dotlock;
       FILE *fp;
       FILE *nfp;
       int rc;
       unsigned ut;

       char *deleted_event=0;      /* Filename of deleted event */
       int is_cancelled=0;
       int is_booked=0;
       int was_booked=0;

       ci->errcode=0;


       if (ae->tmpfile == NULL)    /* Already commited */
       {
              ci->errcode=PCP_ERR_EVENTNOTFOUND;
              return (-1);
       }

       if (ci->n_event_times <= 0)
       {
              ci->errcode=PCP_ERR_CONFLICT;
              return (-1);
       }

       /* Sort event times in chronological order */

       times=pcp_add_sort_times(ci->event_times,
                                 ci->n_event_times);
       if (!times)
              return (-1);

       /* Use a dotlock to protect: reading old index + checking for
       ** conflicts, writing a new index, updating everything */

       dotlock=acquire_dotlock(pd);

       if (!dotlock)
       {
              ci->errcode=PCP_ERR_LOCK;
              free(times);
              return (-1);
       }

       rc= -1;
       fp=fopen(pd->indexname, "a+");
       if (fp && fseek(fp, 0L, SEEK_SET) >= 0)
       {
              nfp=fopen(pd->newindexname, "w");
              if (nfp)
              {
                     struct line_buffer pi;

                     if (lb_init(&pi) == 0)
                     {
                            rc= 0;
                            while (lb_read(fp, &pi) == 0)
                            {
                                   if (ae->booked &&
                                       lb_is_eventid(&pi,
                                                   ae->eventid.eventid))
                                   {
                                          was_booked=1;
                                          if (bookmode)
                                                 continue;
                                          /* Drop old booking */

                                          if (lb_remove_field(&pi, nfp,
                                                            BOOKED_FIELD,
                                                            NULL,
                                                            NULL))
                                                 rc= -1;
                                          is_booked=1;
                                          continue;
                                   }
                                   if (ae->oldeventid
                                       && lb_is_eventid(&pi,
                                                      ae->oldeventid))
                                   {
                                          if (lb_is_cancelled(&pi))
                                                 is_cancelled=1;
                                          if (deleted_event) /* ??? */
                                                 free(deleted_event);
                                          deleted_event=lb_filename
                                                 (pd, &pi);
                                          if (!deleted_event)
                                                 rc= -1;
                                          if (bookmode)
                                          {
                                                 const char *pendel=
                                                        lb_is_pendel(&pi);
                                                 if (pendel)
                                                 {
                                                        /* Event is locked by another book/update? */

                                                        char *delid=lb_field_value_buf(pendel);

                                                        if (!delid)
                                                               rc= -1;
                                                        else if (strcmp(delid, ae->eventid.eventid))
                                                        {
                                                               int flag=0;
                                                               /*
                                                               ** Possibly, but make sure the locking
                                                               ** event actually exists.
                                                               */
                                                               if (eventexists(pd, delid, &flag))
                                                                      rc= -1;
                                                               else if (flag)
                                                               {
                                                                      rc= -1;
                                                                      ci->errcode=PCP_ERR_EVENTLOCKED;
                                                               }
                                                        }
                                                        fprintf(nfp, "%s\n",
                                                               pi.buffer);
                                                        free(delid);
                                                 }
                                                 else
                                                 {
                                                        lb_remove_field(&pi,
                                                                      nfp,
                                                                      PENDEL_FIELD,
                                                                      PENDEL_FIELD,
                                                                      ae->eventid.eventid);
                                                 }
                                                 /* Dont del just yet */
                                          }
                                          continue;
                                   }
                                   fprintf(nfp, "%s\n", pi.buffer);

                                   /* Check for conflicts UNLESS */

                                   if ((ci->flags & PCP_OK_CONFLICT)
                                       == 0 &&
                                       /* Conflics are OK */

                                       (!ae->booked || bookmode) &&
                                       /*
                                       ** We're not committing a booked
                                       ** event (check for conflicts at
                                       ** time of booking).
                                       */

                                       !lb_is_cancelled(&pi) &&
                                       /* This event is cancelled */

                                       pcp_is_conflict(&pi,
                                                     times,
                                                     ci->n_event_times,
                                                     ci,
                                                     NULL)
                                       )
                                   {
                                          rc= -1;
                                   }
                            }

                            if (rc == 0 && !ferror(fp) && !ferror(nfp)
                                && !is_booked)
                            {
                                   /* Add a new index record */

                                   const char *p=
                                          strrchr(ae->newfile, '/');

                                   if (p)
                                          ++p;
                                   else
                                          p=ae->newfile;

                                   fprintf(nfp, "%s\t%s",
                                          ae->eventid.eventid, p);

                                   /*
                                   ** If older event is cancelled, so
                                   ** is this event.
                                   */

                                   if (is_cancelled)
                                   {
                                          fprintf(nfp, "\t"
                                                 CANCELLED_FIELD);
                                   }

                                   if (ci->flags & PCP_BYPROXY)
                                          fprintf(nfp, "\t"
                                                 PROXY_FIELD);

                                   if (bookmode)
                                   {
                                          time_t book_time;

                                          time(&book_time);
                                          fprintf(nfp, "\t" BOOKED_FIELD
                                                 "=%lu",
                                                 (unsigned long)
                                                 book_time);
                                   }

                                   for (ut=0; ut<ci->n_event_times; ut++)
                                          fprintf(nfp, "\t"
                                                 TIME_FIELD
                                                 "=%lu,%lu",
                                                 (unsigned long)
                                                 times[ut]->start,
                                                 (unsigned long)
                                                 times[ut]->end);


                                   for (ut=0; ut<ae->n_event_participants;
                                        ut++)
                                   {
                                          const char *p=
                                                 ae->event_participants
                                                 [ut].address;
                                          const char *q=
                                                 ae->event_participants
                                                 [ut].eventid;

                                          if (!p)
                                                 continue;

                                          fprintf(nfp,
                                                 "\t"
                                                 PARTICIPANT_FIELD
                                                 "=%s%s%s", p,
                                                 q ? " ":"", q ? q:"");

                                          /* Sanity check: */

                                          while (*p)
                                          {
                                                 if ((int)
                                                     (unsigned char)*p
                                                     <= ' ')
                                                 {
                                                        rc= -1;
                                                        errno=EINVAL;
                                                 }
                                                 ++p;
                                          }
                                   }

                                   fprintf(nfp, "\n");
                            }
                            if (ae->booked && !was_booked)
                            {
                                   rc= -1;
                                   ci->errcode=PCP_ERR_EVENTNOTFOUND;
                                   ae->booked=0;
                                   /* Booked event disappeared */
                            }

                            if (rc == 0 && 
                                (fflush(nfp) < 0 || ferror(nfp)))
                                   rc= -1;

                            lb_destroy(&pi);
                     }
                     if (fclose(nfp))
                            rc= -1;
              }
              if (fclose(fp))
                     rc= -1;

              if (rc == 0 && !bookmode)
              {
                     if (rename(ae->tmpfile, ae->newfile))
                            rc= -1;
              }

              if (rc == 0)
              {
                     if (rename(pd->newindexname, pd->indexname))
                            rc=-1;
              }

              if (rc == 0 && !bookmode)
              {
                     if (deleted_event)
                            unlink(deleted_event);
                     free(ae->tmpfile);
                     ae->tmpfile=0;
                     ae->booked=0;
              }
              if (rc == 0 && bookmode)
                     ae->booked=1;
       }
       else if (fp)
              fclose(fp);

       if (deleted_event)
              free(deleted_event);
       markchanged(pd);
       release_dotlock(pd, dotlock);
       free(times);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* dotlockname ( struct PCPdir pd) [static]

Definition at line 248 of file pcpdir.c.

{
       char *p=malloc(strlen(pd->dirname)+sizeof("/.lock"));

       if (!p)
              return (NULL);

       return (strcat(strcpy(p, pd->dirname), "/.lock"));
}

Here is the caller graph for this function:

static const char* errmsg ( struct PCP pcp) [static]

Definition at line 98 of file pcpdir.c.

{
       return (strerror(errno));
}

Here is the caller graph for this function:

static int event_expired ( struct line_buffer pi,
time_t  when 
) [static]

Definition at line 1682 of file pcpdir.c.

{
       const char *p;

       for (p=lb_first_field(pi); p; p=lb_next_field(pi))
       {
              time_t start_time;
              time_t end_time;

              if (!lb_is_field(p, TIME_FIELD))
                     continue;

              if (parse_time_field(lb_field_value(p),
                                 &start_time, &end_time))
                     continue;
              if (end_time > when)
                     return (0);
       }
       return (1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int eventexists ( struct PCPdir pd,
const char *  e,
int *  flag 
) [static]

Definition at line 1149 of file pcpdir.c.

{
       FILE *fp=fopen(pd->indexname, "r");
       struct line_buffer pi;

       if (!fp)
              return (0);

       if (fseek(fp, 0L, SEEK_SET) < 0)
              return (-1);


       if (lb_init(&pi))
       {
              fclose(fp);
              return (-1);
       }

       *flag=0;

       while (lb_read(fp, &pi) == 0)
       {
              if (lb_is_eventid(&pi, e))
              {
                     *flag=1;
                     break;
              }
       }
       lb_destroy(&pi);
       if (ferror(fp))
       {
              fclose(fp);
              return (-1);
       }

       if (fclose(fp))
              return (-1);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* getauthtoken ( struct PCP pcp) [static]

Definition at line 107 of file pcpdir.c.

{
       return (NULL);
}

Here is the caller graph for this function:

static int kill_stale_lock ( struct PCPdir pd,
const char *  stale_lock,
time_t *  tm 
) [static]

Definition at line 299 of file pcpdir.c.

{
       int fd;
       char buffer[HOSTNAMELEN+256];
       int n;
       struct stat stat_buf;

       fd=open(stale_lock, O_RDONLY);
       if (fd < 0)
       {
              if (errno == ENOENT)
                     return (0);
              return (-1);
       }

       n=read(fd, buffer, sizeof(buffer)-1);

       if (n < 0 || fstat(fd, &stat_buf) < 0)
       {
              close(fd);
              return (-1);
       }

       *tm=stat_buf.st_mtime;
       close(fd);

       if (n > 0 && buffer[n-1] == '\n')
       {
              char *p;

              buffer[n-1]=0;

              p=strchr(buffer, ' ');
              if (p)
              {
                     *p++=0;
                     if (strcmp(p, pd->hostname_buf) == 0)
                            /* Dot-lock created on this server */
                     {
                            pid_t pn=atol(buffer);

                            if (pn > 1)
                            {
                                   if (kill(pn, 0) == 0 ||
                                       errno != ESRCH)
                                   {
                                          return (2);
                                   }
                                   /* Process doesn't exist no more */

                                   if (unlink(stale_lock) == 0
                                       || errno == ENOENT)
                                   {
                                          return (1);
                                   }
                                   return (-1);
                            }

                            fprintf(stderr, "INFO: "
                                   "Corrupted dot-lock - removing %s\n",
                                   stale_lock);

                            if (unlink(stale_lock) == 0
                                || errno == ENOENT)
                            {
                                   return (1);
                            }
                            return (-1);
                     }

                     return (1);
              }
       }

       fprintf(stderr, "INFO: Corrupted dot-lock - removing %s\n", stale_lock);

       if (unlink(stale_lock) == 0
           || errno == ENOENT)
       {
              return (1);
       }

       return (-1);
}

Here is the caller graph for this function:

static void lb_destroy ( struct line_buffer pi) [static]

Definition at line 850 of file pcpdir.c.

{
       free(pi->buffer);
}

Here is the caller graph for this function:

static char* lb_event_id ( struct line_buffer pi) [static]

Definition at line 897 of file pcpdir.c.

{
       char *p=strchr(pi->buffer, '\t');
       char *q;

       if (!p)
              return (strdup("")); /* Corrupted index file */

       q=malloc(p-pi->buffer+1);

       if (!q)
              return (NULL);

       memcpy(q, pi->buffer, p-pi->buffer);
       q[p-pi->buffer]=0;
       return (q);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* lb_field_value ( const char *  p) [static]

Definition at line 1019 of file pcpdir.c.

{
       while (p && *p && *p != '\t')
              if ( *p++ == '=')
                     return (p);
       return (NULL);
}

Here is the caller graph for this function:

static char* lb_field_value_buf ( const char *  p) [static]

Definition at line 1047 of file pcpdir.c.

{
       const char *q;
       char *r;

       while (p && *p && *p != '\t')
              if ( *p++ == '=')
                     break;

       if (!p)
              return (strdup(""));

       q=strchr(p, '\t');
       if (!q)
              return (strdup(p));

       r=malloc(q-p+1);

       if (!r)
              return (NULL);

       memcpy(r, p, q-p);
       r[q-p]=0;
       return (r);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* lb_filename ( struct PCPdir pd,
struct line_buffer pi 
) [static]

Definition at line 915 of file pcpdir.c.

{
       char *p=strchr(pi->buffer, '\t');
       char *q, *r;

       if (!p)
              return (strdup("")); /* Corrupted index file */

       ++p;
       r=strchr(p, '\t');
       if (!r)
              r=p+strlen(p);

       q=malloc(strlen(pd->dirname)+2+ (r-p));

       if (!q)
              return (NULL);

       strncat(strcat(strcpy(q, pd->dirname), "/"), p, r-p);
       return (q);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* lb_filename_nodir ( struct line_buffer pi) [static]

Definition at line 937 of file pcpdir.c.

{
       char *p=strchr(pi->buffer, '\t');
       char *q, *r;

       if (!p)
              return (strdup("")); /* Corrupted index file */

       ++p;
       r=strchr(p, '\t');
       if (!r)
              r=p+strlen(p);

       q=malloc(1+(r-p));

       if (!q)
              return (NULL);

       *q=0;
       strncat(q, p, r-p);
       return (q);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* lb_first_field ( struct line_buffer pi) [static]

Definition at line 960 of file pcpdir.c.

{
       char *p;

       p=pi->buffer ? strchr(pi->buffer, '\t'):NULL;

       if (p)
       {
              ++p;   /* p now is the filename */
              p=strchr(p, '\t');
              if (p)
                     ++p;
       }

       return (pi->next_field=p);
}

Here is the caller graph for this function:

static int lb_init ( struct line_buffer pi) [static]

Definition at line 841 of file pcpdir.c.

{
       pi->bufsiz=BUFSIZ;
       pi->buffer=malloc(pi->bufsiz);
       if (!pi->buffer)
              return (-1);
       return (0);
}

Here is the caller graph for this function:

static int lb_is_booked ( struct line_buffer pi,
time_t *  t 
) [static]

Definition at line 1027 of file pcpdir.c.

{
       const char *p;

       for (p=lb_first_field(pi); p; p=lb_next_field(pi))
              if (lb_is_field(p, BOOKED_FIELD))
              {
                     const char *q=lb_field_value(p);
                     unsigned long ul;

                     if (q && sscanf(q, "%lu", &ul) == 1)
                     {
                            if (t)
                                   *t= (time_t)ul;
                            return (1);
                     }
              }
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int lb_is_cancelled ( struct line_buffer pi) [static]

Definition at line 999 of file pcpdir.c.

{
       const char *p;

       for (p=lb_first_field(pi); p; p=lb_next_field(pi))
              if (lb_is_field(p, CANCELLED_FIELD))
                     return (1);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int lb_is_eventid ( struct line_buffer pi,
const char *  ei 
) [static]

Definition at line 889 of file pcpdir.c.

{
       int l=strlen(ei);
       const char *p=pi->buffer;

       return (p && strncmp(p, ei, l) == 0 && p[l] == '\t');
}

Here is the caller graph for this function:

static int lb_is_field ( const char *  p,
const char *  n 
) [static]

Definition at line 986 of file pcpdir.c.

{
       if (p)
       {
              int l=strlen(n);

              if (memcmp(p, n, l) == 0 &&
                  (p[l] == '=' || p[l] == '\t' || p[l] == 0))
                     return (1);
       }
       return (0);
}

Here is the caller graph for this function:

static const char* lb_is_pendel ( struct line_buffer pi) [static]

Definition at line 1073 of file pcpdir.c.

{
       const char *p;

       for (p=lb_first_field(pi); p; p=lb_next_field(pi))
              if (lb_is_field(p, PENDEL_FIELD))
                     return (p);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int lb_is_proxy ( struct line_buffer pi) [static]

Definition at line 1009 of file pcpdir.c.

{
       const char *p;

       for (p=lb_first_field(pi); p; p=lb_next_field(pi))
              if (lb_is_field(p, PROXY_FIELD))
                     return (1);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* lb_next_field ( struct line_buffer pi) [static]

Definition at line 977 of file pcpdir.c.

{
       char *p=pi->next_field ? strchr(pi->next_field, '\t'):NULL;

       if (p)
              ++p;
       return (pi->next_field=p);
}

Here is the caller graph for this function:

static int lb_read ( FILE *  fp,
struct line_buffer pi 
) [static]

Definition at line 855 of file pcpdir.c.

{
       int n=0;
       int c;

       for (;;)
       {
              if (n >= pi->bufsiz)
              {
                     int news=pi->bufsiz + BUFSIZ;
                     char *newp=realloc(pi->buffer, news);

                     if (!newp)
                            return (-1);

                     pi->buffer=newp;
                     pi->bufsiz=news;
              }

              c=getc(fp);
              if (c == EOF)
                     return (-1);

              if (c == '\n')
              {
                     pi->buffer[n]=0;
                     break;
              }
              pi->buffer[n++]=c;
       }

       return (0);
}

Here is the caller graph for this function:

static int lb_remove_field ( struct line_buffer pi,
FILE *  nfp,
const char *  fieldname,
const char *  newfield,
const char *  newvalue 
) [static]

Definition at line 1083 of file pcpdir.c.

{
       char *q;
       const char *cp;

       q=lb_event_id(pi);
       if (!q)
              return (-1);

       fprintf(nfp, "%s\t", q);
       free(q);
       q=lb_filename_nodir(pi);
       if (!q)
              return (-1);
       fprintf(nfp, "%s", q);
       free(q);

       for (cp=lb_first_field(pi); cp; cp=lb_next_field(pi))
       {
              const char *cc;

              if (lb_is_field(cp, fieldname))
                  continue;

              cc=strchr(cp, '\t');
              if (!cc) cc=cp+strlen(cp);

              putc('\t', nfp);
              if (fwrite(cp, cc-cp, 1, nfp) != 1)
                     break;
       }
       if (newfield)
       {
              fprintf(nfp, "\t%s", newfield);
              if (newvalue)
                     fprintf(nfp, "=%s", newvalue);
       }
       putc('\n', nfp);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int listacl ( struct PCPdir pd,
int(*)(const char *, int, void *)  func,
void *  arg 
) [static]

Definition at line 2487 of file pcpdir.c.

{
       char *aclname;
       char buf[1024];
       FILE *fp;

       aclname=malloc(strlen(pd->dirname)+sizeof("/acl"));

       if (!aclname)
              return (-1);

       strcat(strcpy(aclname, pd->dirname), "/acl");

       fp=fopen(aclname, "r");
       free(aclname);

       if (fp)
       {
              while (fgets(buf, sizeof(buf), fp))
              {
                     char *p;
                     int rc;

                     for (p=buf; *p; p++)
                            if (isspace((int)(unsigned char)*p))
                            {
                                   *p++=0;
                                   break;
                            }

                     rc= (*func)(buf, atoi(p), arg);
                     if (rc)
                     {
                            fclose(fp);
                            return (rc);
                     }
              }
              fclose(fp);
       }
       return (0);
}

Here is the caller graph for this function:

static int listallevents ( struct PCPdir pd,
struct PCP_list_all li 
) [static]

Definition at line 1820 of file pcpdir.c.

{
       FILE *fp;
       struct line_buffer lb;
       int rc=0;
       const char *p;

       if ((fp=fopen(pd->indexname, "r")) == NULL)
              return (0);   /* Empty calendar */

       if (lb_init(&lb) == 0)
       {
              while (lb_read(fp, &lb) == 0)
              {
                     char *event_id=lb_event_id(&lb);

                     if (!event_id)
                     {
                            rc= -1;
                            break;
                     }

                     li->event_id=event_id;

                     for (p=lb_first_field(&lb); p; p=lb_next_field(&lb))
                     {
                            if (lb_is_field(p, TIME_FIELD))
                            {
                                   time_t start_time;
                                   time_t end_time;

                                   if (parse_time_field(lb_field_value(p),
                                                      &start_time,
                                                      &end_time))
                                          continue;

                                   if (li->list_from
                                       && li->list_from == li->list_to)
                                   {
                                          if (li->list_from < start_time
                                              || li->list_to >= end_time)
                                                 continue;
                                   }
                                   else
                                   {
                                          if (li->list_from &&
                                              end_time <= li->list_from)
                                                 continue;

                                          if (li->list_to &&
                                              start_time >= li->list_to)
                                                 continue;
                                   }
                                   li->event_from=start_time;
                                   li->event_to=end_time;

                                   if ((rc= (*li->callback_func)
                                        (li, li->callback_arg)) != 0)
                                          break;
                            }
                            if (rc) break;

                     }

                     free(event_id);
                     if (rc)
                            break;
              }
              lb_destroy(&lb);
       }
       fclose(fp);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void markchanged ( struct PCPdir pd) [static]

Definition at line 275 of file pcpdir.c.

{
       char *p=changedname(pd);
       int n;

       if (!p) return;

       n=open(p, O_RDWR|O_CREAT, 0600);
       if (n >= 0)
              close(n);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void mkunique ( struct PCPdir pd) [static]

Definition at line 231 of file pcpdir.c.

{
       struct timeval tv;

       gettimeofday(&tv, NULL);

       sprintf(pd->unique_filename_buf, "%lu.%lu.%lu_%u.",
              (unsigned long)tv.tv_sec,
              (unsigned long)tv.tv_usec,
              (unsigned long)getpid(),
              ++pd->uniq_cnt);

       strncat(pd->unique_filename_buf, pd->hostname_buf,
              sizeof(pd->unique_filename_buf)-1
              -strlen(pd->unique_filename_buf));
}

Here is the caller graph for this function:

static struct PCPdir_new_eventid * neweventid ( struct PCPdir pd,
const char *  oldeventid_arg,
struct PCP_save_event se 
) [static, read]

Definition at line 604 of file pcpdir.c.

{
       unsigned ut;

       struct PCPdir_new_eventid *p=(struct PCPdir_new_eventid *)
              malloc(sizeof(struct PCPdir_new_eventid));

       if (!p)
              return (NULL);

       mkunique(pd);

       p->eventid.eventid=malloc(strlen(pd->unique_filename_buf)+
                              strlen(pd->username)+2);
       if (!p->eventid.eventid)
       {
              free(p);
              return (NULL);
       }

       strcat(strcat(strcpy(p->eventid.eventid, pd->unique_filename_buf),
                    "@"), pd->username);

       p->tmpfile=malloc(strlen(pd->unique_filename_buf)
                       +strlen(pd->dirname)+10);
       if (!p->tmpfile)
       {
              free(p->eventid.eventid);
              free(p);
              return (NULL);
       }
       strcat(strcat(strcat(strcpy(p->tmpfile, pd->dirname),
                          "/."), pd->unique_filename_buf), ".tmp");

       p->newfile=malloc(strlen(pd->unique_filename_buf)
                       +strlen(pd->dirname)+2);
       if (!p->newfile)
       {
              free(p->tmpfile);
              free(p->eventid.eventid);
              free(p);
              return (NULL);
       }
       strcat(strcat(strcpy(p->newfile, pd->dirname),
                    "/"), pd->unique_filename_buf);

       if (oldeventid_arg)
       {
              if ((p->oldeventid=strdup(oldeventid_arg)) == NULL)
              {
                     free(p->newfile);
                     free(p->tmpfile);
                     free(p->eventid.eventid);
                     free(p);
                     return (NULL);
              }
       }
       else
              p->oldeventid=0;
       p->booked=0;

       p->event_participants=NULL;
       p->n_event_participants=0;

       for (ut=0; ut<se->n_event_participants; ut++)
       {
              const char *q;

              for (q=se->event_participants[ut].address; *q; q++)
                     if (isspace((int)(unsigned char)*q))
                     {
                            errno=EINVAL;
                            destroyeventid(pd, p);
                            return (NULL);
                     }

              for (q=se->event_participants[ut].eventid; q && *q; q++)
                     if (isspace((int)(unsigned char)*q))
                     {
                            errno=EINVAL;
                            destroyeventid(pd, p);
                            return (NULL);
                     }
       }

       if (se->n_event_participants > 0)
       {
              if ((p->event_participants=
                   malloc( sizeof (*p->event_participants)
                          * se->n_event_participants)) == 0)
              {
                     destroyeventid(pd, p);
                     return (NULL);
              }

              for ( ; p->n_event_participants < se->n_event_participants;
                    ++p->n_event_participants)
              {
                     p->event_participants[p->n_event_participants]
                            .eventid=NULL;

                     if (se->event_participants[p->n_event_participants]
                         .eventid
                         && (p->event_participants[p->n_event_participants]
                            .eventid=strdup(se->event_participants
                                          [p->n_event_participants]
                                          .eventid))
                          == NULL)
                     {
                            destroyeventid(pd, p);
                            return (NULL);
                     }

                     if ( (p->event_participants[p->n_event_participants]
                           .address=strdup(se->event_participants
                                         [p->n_event_participants]
                                         .address))
                          == NULL)
                     {
                            if (p->event_participants
                                [p->n_event_participants].eventid)
                                   free(p->event_participants
                                        [p->n_event_participants]
                                        .eventid);
                            destroyeventid(pd, p);
                            return (NULL);
                     }
              }
       }

       if (saveevent(pd, p, se))
       {
              destroyeventid(pd, p);
              p=NULL;
       }

       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void noop ( struct PCP pcp) [static]

Definition at line 103 of file pcpdir.c.

{
}

Here is the caller graph for this function:

static int parse_time_field ( const char *  p,
time_t *  start_time,
time_t *  end_time 
) [static]

Definition at line 1705 of file pcpdir.c.

{
       if (!p)
              return (-1);

       *start_time=0;
       *end_time=0;

       while (*p && isdigit((int)(unsigned char)*p))
       {
              *start_time=*start_time * 10 + (*p-'0');
              ++p;
       }
       if (*p != ',')
              return (-1);

       ++p;
       while (*p && isdigit((int)(unsigned char)*p))
       {
              *end_time=*end_time * 10 + (*p-'0');
              ++p;
       }
       return (0);
}

Here is the caller graph for this function:

static void pcp_close_dir ( struct PCPdir pd) [static]

Definition at line 221 of file pcpdir.c.

{
       free(pd->newindexname);
       free(pd->indexname);
       free(pd->dirname);
       free(pd->username);
       free(pd);
}

Here is the caller graph for this function:

static int pcp_is_conflict ( struct line_buffer lb,
const struct PCP_event_time **  t,
unsigned  n,
struct PCP_commit ae,
struct PCP_uncancel un 
) [static]

Definition at line 1731 of file pcpdir.c.

{
       unsigned i;
       const char *p;
       int rc=0;

       char *event_id=lb_event_id(lb);

       if (!event_id)
              return (-1);

       for (p=lb_first_field(lb); p; p=lb_next_field(lb))
       {
              time_t start_time;
              time_t end_time;

              if (!lb_is_field(p, TIME_FIELD))
                     continue;

              if (parse_time_field(lb_field_value(p),
                                 &start_time, &end_time))
                     continue;

              for (i=0; i<n; i++)
              {
                     time_t com_start;
                     time_t com_end;

                     if (start_time >= t[i]->end)
                            continue;
                     if (t[i]->start >= end_time)
                            continue;

                     com_start=start_time;
                     com_end=end_time;
                     if (t[i]->start > com_start)
                            com_start=t[i]->start;
                     if (t[i]->end < com_end)
                            com_end=t[i]->end;

                     rc= -1;
                     if (ae)
                     {
                            ae->errcode=PCP_ERR_CONFLICT;
                            if (ae->add_conflict_callback)
                            {
                                   rc=(*ae->add_conflict_callback)
                                          (event_id, com_start,
                                           com_end,
                                           "@",
                                           ae->add_conflict_callback_ptr
                                           );
                                   if (rc)
                                   {
                                          ae->errcode=0;
                                          break;
                                   }
                                   rc= -1;
                            }
                     }

                     if (un)
                     {
                            un->errcode=PCP_ERR_CONFLICT;
                            if (un->uncancel_conflict_callback)
                            {
                                   rc=(*un->uncancel_conflict_callback)
                                          (event_id, com_start,
                                           com_end, "@",
                                           un->uncancel_conflict_callback_ptr
                                           );
                                   if (rc)
                                   {
                                          un->errcode=0;
                                          break;
                                   }
                                   rc= -1;
                            }
                     }
              }

       }
       free(event_id);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct PCP* pcp_open_dir ( const char *  dirname,
const char *  username 
) [read]

Definition at line 112 of file pcpdir.c.

{
       struct PCPdir *pd=(struct PCPdir *)malloc(sizeof(struct PCPdir));

       if (!pd)
              return (NULL);

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

       pd->username=strdup(username);
       if (!pd->username)
       {
              free(pd);
              return (NULL);
       }

       pd->dirname=strdup(dirname);

       if (!pd->dirname)
       {
              free(pd);
              return (NULL);
       }

       pd->indexname=malloc(strlen(dirname)+sizeof("/index"));
       if (!pd->indexname)
       {
              free(pd->username);
              free(pd->dirname);
              free(pd);
              return (NULL);
       }
       strcat(strcpy(pd->indexname, dirname), "/index");

       pd->newindexname=malloc(strlen(dirname)+sizeof("/.index.tmp"));
       if (!pd->newindexname)
       {
              free(pd->username);
              free(pd->indexname);
              free(pd->dirname);
              free(pd);
              return (NULL);
       }
       strcat(strcpy(pd->newindexname, dirname), "/.index.tmp");

       pd->hostname_buf[sizeof(pd->hostname_buf)-1]=0;
       pd->hostname_buf[0]=0;
       if (gethostname(pd->hostname_buf, sizeof(pd->hostname_buf)-1) < 0
           || pd->hostname_buf[0] == 0)
              strcpy(pd->hostname_buf, "localhost");


       pd->pcp.authtoken_func=getauthtoken;
       pd->pcp.close_func= (void (*)(struct PCP *)) pcp_close_dir;
       pd->pcp.cleanup_func= (int (*)(struct PCP *)) cleanup;

       pd->pcp.create_new_eventid_func=
              (struct PCP_new_eventid *(*)(struct PCP *, const char *,
                                        struct PCP_save_event *))
              neweventid;

       pd->pcp.destroy_new_eventid_func=
              (void (*)(struct PCP *, struct PCP_new_eventid *))
              destroyeventid;

       pd->pcp.commit_func=
              (int (*)(struct PCP *, struct PCP_new_eventid *,
                      struct PCP_commit *))
              commitevent;

       pd->pcp.book_func=
              (int (*)(struct PCP *, struct PCP_new_eventid *,
                      struct PCP_commit *))
              bookevent;

       pd->pcp.list_all_func=
              (int (*)(struct PCP *, struct PCP_list_all *))
              listallevents;

       pd->pcp.cancel_func=
              (int (*)(struct PCP *, const char *, int *))
              cancelevent;

       pd->pcp.uncancel_func=
              (int (*)(struct PCP *, const char *, int,
                      struct PCP_uncancel *))
              uncancelevent;

       pd->pcp.delete_func=
              (int (*)(struct PCP *, struct PCP_delete *))
              deleteevent;

       pd->pcp.retr_func=
              (int (*)(struct PCP *, struct PCP_retr *))
              retrevent;

       pd->pcp.errmsg_func=errmsg;

       pd->pcp.noop_func=noop;

       pd->pcp.acl_func=
              (int (*)(struct PCP *, const char *, int))setacl;
       pd->pcp.listacl_func=
              (int (*)(struct PCP *, int (*)(const char *, int, void *),
                      void *))listacl;

       return ((struct PCP *)pd);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int read_event_times ( struct line_buffer pi,
struct PCP_event_time **  time_ret,
unsigned *  time_n_ret 
) [static]

Definition at line 1894 of file pcpdir.c.

{
       const char *c;
       unsigned n;
       time_t start_time, end_time;

       *time_n_ret=0;
       *time_ret=NULL;

       for (c=lb_first_field(pi); c; c=lb_next_field(pi))
              if (lb_is_field(c, TIME_FIELD) &&
                  parse_time_field(lb_field_value(c),
                                 &start_time, &end_time) == 0)
                     ++ *time_n_ret;

       if (!*time_n_ret)
              return (0);

       if ( (*time_ret=(struct PCP_event_time *)malloc
             (sizeof(struct PCP_event_time)* *time_n_ret)) == NULL)
              return (-1);

       n=0;
       for (c=lb_first_field(pi); c; c=lb_next_field(pi))
              if (lb_is_field(c, TIME_FIELD) &&
                  parse_time_field(lb_field_value(c),
                                 &start_time, &end_time) == 0)
              {
                     (*time_ret)[n].start=start_time;
                     (*time_ret)[n].end=end_time;
                     ++n;
              }
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void release_dotlock ( struct PCPdir pd,
char *  n 
) [static]

Definition at line 569 of file pcpdir.c.

{
       FILE *fp;
       char buf[HOSTNAMELEN*2];

       fp=fopen(n, "r");

       if (fp && fgets(buf, sizeof(buf), fp) != NULL)
       {
              char *p=strchr(buf, '\n');

              if (p)
                     *p=0;

              p=strchr(buf, ' ');
              if (p)
              {
                     *p++=0;

                     if (atol(buf) == getpid() &&
                         strcmp(p, pd->hostname_buf) == 0)
                     {
                            fclose(fp);
                            unlink(n);
                            free(n);
                            return;
                     }
              }
       }
       if (fp)
              fclose(fp);
       fprintf(stderr, "ALERT: Dotlock unexpectedly gone: %s\n", n);
       free(n);
}

Here is the caller graph for this function:

static int retrevent ( struct PCPdir pd,
struct PCP_retr ri 
) [static]

Definition at line 2208 of file pcpdir.c.

{
       FILE *fp;
       int rc;

       rc= -1;

       fp=fopen(pd->indexname, "r");
       if (fp && fseek(fp, 0L, SEEK_SET) >= 0)
       {
              struct line_buffer pi;

              if (lb_init(&pi) == 0)
              {
                     rc= 0;
                     while (lb_read(fp, &pi) == 0)
                     {
                            const char *c;
                            char *filename;
                            unsigned x;
                            int status;

                            for (x=0; ri->event_id_list[x]; x++)
                                   if (lb_is_eventid(&pi,
                                                   ri->event_id_list[x])
                                       )
                                          break;
                            if (!(ri->event_id=ri->event_id_list[x]))
                                   continue;

                            filename=lb_filename(pd, &pi);
                            if (!filename)
                            {
                                   rc= -1;
                                   break;
                            }
                            if (!*filename)
                            {
                                   free(filename);
                                   continue;
                            }

                            status=0;
                            if (lb_is_cancelled(&pi))
                                   status |= LIST_CANCELLED;
                            if (lb_is_booked(&pi, NULL))
                                   status |= LIST_BOOKED;
                            if (lb_is_proxy(&pi))
                                   status |= LIST_PROXY;

                            if (ri->callback_retr_status)
                            {
                                   rc= (*ri->callback_retr_status)
                                          (ri, status,
                                           ri->callback_arg);
                                   if (rc)
                                          break;
                            }

                            for (c=lb_first_field(&pi); c;
                                 c=lb_next_field(&pi))
                            {
                                   if (lb_is_field(c, TIME_FIELD))
                                   {
                                          time_t from, to;

                                          if (!ri->callback_retr_date)
                                                 continue;

                                          if (parse_time_field
                                              (lb_field_value(c),
                                               &from, &to))
                                                 continue;

                                          rc=(*ri->
                                              callback_retr_date)
                                                 (ri, from, to,
                                                  ri->callback_arg);
                                          if (rc)
                                                 break;
                                          continue;
                                   }

                                   if (lb_is_field(c, PARTICIPANT_FIELD))
                                   {
                                          char *pp, *qq;;
                                          if (ri->
                                              callback_retr_participants
                                              == NULL)
                                                 continue;

                                          pp=lb_field_value_buf(c);

                                          if (!pp)
                                          {
                                                 rc= -1;
                                                 break;
                                          }

                                          if ((qq=strchr(pp, ' ')) != 0)
                                                 *qq++=0;

                                          rc=(*ri->
                                              callback_retr_participants)
                                                 (ri, pp, qq,
                                                  ri->callback_arg);
                                          free(pp);
                                          if (rc)
                                                 break;
                                          continue;
                                   }
                            }

                            if (rc)
                            {
                                   free(filename);
                                   break;
                            }

                            if (ri->callback_headers_func == NULL &&
                                ri->callback_rfc822_func == NULL)
                            {
                                   free(filename);
                                   continue;
                            }

                            if (ri->callback_begin_func)
                            {
                                   rc= (*ri->callback_begin_func)
                                          (ri, ri->callback_arg);
                                   if (rc)
                                   {
                                          free(filename);
                                          break;
                                   }
                            }

                            if (ri->callback_rfc822_func)
                                   rc=retrrfc822(pd, ri, filename);
                            else if (ri->callback_headers_func)
                                   rc=retrheaders(pd, ri, filename);

                            if (rc == 0 && ri->callback_end_func)
                                   rc= (*ri->callback_end_func)
                                          (ri, ri->callback_arg);

                            free(filename);
                            if (rc)
                                   break;
                     }
                     lb_destroy(&pi);
              }
              fclose(fp);
       }
       else if (fp)
              fclose(fp);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int retrheaders ( struct PCPdir pd,
struct PCP_retr ri,
const char *  filename 
) [static]

Definition at line 2367 of file pcpdir.c.

{
       FILE *fp=fopen(filename, "r");
       struct rfc822hdr h;
       int rc=0;

       if (!fp)
              return (errno == ENOENT ? 0:-1);

       rfc822hdr_init(&h, 8192);

       while (rfc822hdr_read(&h, fp, NULL, 0) == 0)
       {
              if ((rc= (*ri->callback_headers_func)(ri, h.header,
                                                h.value,
                                                ri->callback_arg)) != 0)
                     break;
       }
       if (rc == 0 && ferror(fp))
              rc= -1;
       rfc822hdr_free(&h);
       fclose(fp);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int retrrfc822 ( struct PCPdir pd,
struct PCP_retr ri,
const char *  filename 
) [static]

Definition at line 2393 of file pcpdir.c.

{
       int fd=open(filename, O_RDONLY);
       char buf[BUFSIZ];
       int n;
       int rc=0;

       if (fd < 0)
              return (errno == ENOENT ? 0:-1);

       while ((n=read(fd, buf, sizeof(buf))) > 0)
              if ((rc= (*ri->callback_rfc822_func)(ri, buf, n,
                                               ri->callback_arg)) != 0)
                     break;
       if (rc == 0 && n < 0)
              rc= -1;
       close(fd);
       return (rc);
}

Here is the caller graph for this function:

static int saveevent ( struct PCPdir pd,
struct PCPdir_new_eventid ne,
struct PCP_save_event si 
) [static]

Definition at line 784 of file pcpdir.c.

{
       char buf[BUFSIZ];
       int n;

       FILE *nf=fopen(ne->tmpfile, "w");

       if (!nf)
              return (-1);

       while ((n=pcp_read_saveevent(si, buf, sizeof(buf))) > 0)
       {
              if (fwrite(buf, n, 1, nf) != 1)
              {
                     fclose(nf);
                     return (-1);
              }
       }

       if (fflush(nf) || ferror(nf))
              n= -1;
       if (fclose(nf))
              n= -1;

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

       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int setacl ( struct PCPdir pd,
const char *  who,
int  flags 
) [static]

Definition at line 2414 of file pcpdir.c.

{
       char *dotlock;
       FILE *fp;
       FILE *nfp;
       int rc;
       char *aclname;
       char *newaclname;
       char buf[1024];

       if (strchr(who, '\r') || strchr(who, '\n') || strlen(who) > 512)
       {
              errno=EINVAL;
              return (-1);
       }

       aclname=malloc(strlen(pd->dirname)+sizeof("/acl"));

       if (!aclname)
              return (-1);

       newaclname=malloc(strlen(pd->dirname)+sizeof("/acl.new"));

       if (!newaclname)
       {
              free(aclname);
              return (-1);
       }

       dotlock=acquire_dotlock(pd);

       if (!dotlock)
       {
              free(newaclname);
              free(aclname);
              return (-1);
       }

       strcat(strcpy(aclname, pd->dirname), "/acl");
       strcat(strcpy(newaclname, pd->dirname), "/acl.new");

       rc= -1;
       nfp=fopen(newaclname, "w");
       if (nfp)
       {
              int l=strlen(who);

              fp=fopen(aclname, "r");
              if (fp)
              {
                     while (fgets(buf, sizeof(buf), fp))
                     {
                            if (strncmp(buf, who, l) == 0 &&
                                isspace((int)(unsigned char)buf[l]))
                                   continue;
                            fprintf(nfp, "%s", buf);
                     }
                     fclose(fp);
              }
              if (flags)
                     fprintf(nfp, "%s\t%d\n", who, flags);
              rc=0;
              if (fflush(nfp) || ferror(nfp))
                     rc= -1;
              if (fclose(nfp) || rename(newaclname, aclname))
                     rc= -1;
       }
       release_dotlock(pd, dotlock);
       free(newaclname);
       free(aclname);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int uncancelevent ( struct PCPdir pd,
const char *  event,
int  flags,
struct PCP_uncancel info 
) [static]

Definition at line 2003 of file pcpdir.c.

{
       char *dotlock;
       FILE *fp;
       FILE *nfp;
       int rc;
       int found=0;
       struct PCP_event_time *old_times=NULL;
       const struct PCP_event_time **old_times_sorted=NULL;
       unsigned n_old_times=0;

       if (info) info->errcode=0;
       dotlock=acquire_dotlock(pd);

       if (!dotlock)
              return (-1);

       rc= -1;
       fp=fopen(pd->indexname, "a+");
       if (fp && fseek(fp, 0L, SEEK_SET) >= 0)
       {
              struct line_buffer pi;

              /* First, find the existing booked times */

              if (lb_init(&pi) == 0)
              {
                     if (info)
                            info->errcode=PCP_ERR_EVENTNOTFOUND;
                     while (lb_read(fp, &pi) == 0)
                     {
                            if (!lb_is_eventid(&pi, event))
                                   continue;
                            if (read_event_times(&pi, &old_times,
                                               &n_old_times) == 0)
                            {
                                   if (fseek(fp, 0L, SEEK_SET) >= 0)
                                          rc=0;
                                   break;
                            }
                     }
                     lb_destroy(&pi);

                     if (rc == 0 && info)
                            info->errcode=0;
              }

              if (rc == 0 && n_old_times &&
                  (old_times_sorted=
                   pcp_add_sort_times(old_times, n_old_times)) == NULL)
                     rc= -1;

              nfp=rc == 0 ? fopen(pd->newindexname, "w"):NULL;
              if (nfp)
              {
                     struct line_buffer pi;

                     if (lb_init(&pi) == 0)
                     {
                            rc= 0;
                            while (lb_read(fp, &pi) == 0)
                            {
                                   char *id=lb_event_id(&pi);

                                   if (!id)
                                   {
                                          rc= -1;
                                          break;
                                   }

                                   if (!lb_is_eventid(&pi, event))
                                   {
                                          if ((flags & PCP_OK_CONFLICT)
                                              == 0 &&
                                              !lb_is_cancelled(&pi))
                                          {
                                                 rc= pcp_is_conflict
                                                        (&pi,
                                                         old_times_sorted,
                                                         n_old_times,
                                                         NULL,
                                                         info);
                                          }
                                          fprintf(nfp, "%s\n",
                                                 pi.buffer);
                                          continue;
                                   }
                                   found=1;
                                   if (!lb_is_cancelled(&pi))
                                   {
                                          /* Already uncanned */
                                          fprintf(nfp, "%s\n",
                                                 pi.buffer);
                                          continue;
                                   }

                                   if (lb_remove_field(&pi, nfp,
                                                     CANCELLED_FIELD,
                                                     NULL,
                                                     NULL))
                                          rc= -1;
                            }
                            lb_destroy(&pi);
                            if (!found)
                            {
                                   if (info)
                                          info->errcode=PCP_ERR_EVENTNOTFOUND;
                                   errno=ENOENT;
                                   rc= -1;
                            }
                     }
                     if (ferror(nfp) || fflush(nfp))
                            rc= -1;
                     if (fclose(nfp))
                            rc= -1;
              }
              fclose(fp);

              if (rc == 0 && rename(pd->newindexname, pd->indexname))
                     rc= -1;
       }
       else if (fp)
              fclose(fp);
       if (old_times_sorted)
              free (old_times_sorted);
       if (old_times)
              free (old_times);
       release_dotlock(pd, dotlock);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function: