Back to index

courier  0.68.2
maildircreate.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2003 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "maildircreate.h"
00007 #include      "maildirmisc.h"
00008 #include      <sys/types.h>
00009 #if    HAVE_SYS_STAT_H
00010 #include      <sys/stat.h>
00011 #endif
00012 
00013 #if TIME_WITH_SYS_TIME
00014 #include      <sys/time.h>
00015 #include      <time.h>
00016 #else
00017 #if HAVE_SYS_TIME_H
00018 #include      <sys/time.h>
00019 #else
00020 #include      <time.h>
00021 #endif
00022 #endif
00023 #if    HAVE_SYS_STAT_H
00024 #include      <sys/stat.h>
00025 #endif
00026 
00027 #if    HAVE_UNISTD_H
00028 #include      <unistd.h>
00029 #endif
00030 #include      <string.h>
00031 #include      <errno.h>
00032 #include      <stdio.h>
00033 #include      <stdlib.h>
00034 #include      <fcntl.h>
00035 #include      "numlib/numlib.h"
00036 
00037 
00038 
00039 FILE *maildir_tmpcreate_fp(struct maildir_tmpcreate_info *info)
00040 {
00041        int fd=maildir_tmpcreate_fd(info);
00042        FILE *fp;
00043 
00044        if (fd < 0)
00045               return NULL;
00046 
00047        fp=fdopen(fd, "w+");
00048 
00049        if (fp == NULL)
00050        {
00051               close(fd);
00052               return NULL;
00053        }
00054 
00055        return fp;
00056 }
00057 
00058 static int maildir_tmpcreate_fd_do(struct maildir_tmpcreate_info *info);
00059 
00060 #define KEEPTRYING   (60 * 60)
00061 #define SLEEPFOR     3
00062 
00063 int maildir_tmpcreate_fd(struct maildir_tmpcreate_info *info)
00064 {
00065        int i;
00066 
00067        if (!info->doordie)
00068               return (maildir_tmpcreate_fd_do(info));
00069 
00070        for (i=0; i<KEEPTRYING / SLEEPFOR; i++)
00071        {
00072               int fd=maildir_tmpcreate_fd_do(info);
00073 
00074               if (fd >= 0 || errno != EAGAIN)
00075                      return fd;
00076 
00077               sleep(SLEEPFOR);
00078        }
00079 
00080        return -1;
00081 }
00082 
00083 static int maildir_tmpcreate_fd_do(struct maildir_tmpcreate_info *info)
00084 {
00085        const char *maildir=info->maildir;
00086        const char *uniq=info->uniq;
00087        const char *hostname=info->hostname;
00088 
00089        char hostname_buf[256];
00090        char time_buf[NUMBUFSIZE];
00091        char usec_buf[NUMBUFSIZE];
00092        char pid_buf[NUMBUFSIZE];
00093        char len_buf[NUMBUFSIZE+3];
00094        char dev_buf[NUMBUFSIZE];
00095        char ino_buf[NUMBUFSIZE];
00096        struct timeval tv;
00097 
00098        struct stat stat_buf;
00099        int fd;
00100 
00101        if (!maildir)
00102               maildir=".";
00103        if (!uniq)
00104               uniq="";
00105 
00106        if (!hostname || !*hostname)
00107        {
00108               hostname_buf[sizeof(hostname_buf)-1]=0;
00109               if (gethostname(hostname_buf, sizeof(hostname_buf)-1) < 0)
00110                      strcpy(hostname_buf, "localhost");
00111               hostname=hostname_buf;
00112        }
00113 
00114        gettimeofday(&tv, NULL);
00115 
00116        libmail_str_time_t(tv.tv_sec, time_buf);
00117        libmail_str_time_t(tv.tv_usec, usec_buf);
00118        libmail_str_pid_t(getpid(), pid_buf);
00119        len_buf[0]=0;
00120        if (info->msgsize > 0)
00121        {
00122               strcpy(len_buf, ",S=");
00123               libmail_str_size_t(info->msgsize, len_buf+3);
00124        }
00125 
00126        if (info->tmpname)
00127               free(info->tmpname);
00128 
00129        info->tmpname=malloc(strlen(maildir)+strlen(uniq)+
00130                           strlen(hostname)+strlen(time_buf)+
00131                           strlen(usec_buf)+
00132                           strlen(pid_buf)+strlen(len_buf)+100);
00133 
00134        if (!info->tmpname)
00135        {
00136               maildir_tmpcreate_free(info);
00137               return -1;
00138        }
00139 
00140        strcpy(info->tmpname, maildir);
00141        strcat(info->tmpname, "/tmp/");
00142        strcat(info->tmpname, time_buf);
00143        strcat(info->tmpname, ".M");
00144        strcat(info->tmpname, usec_buf);
00145        strcat(info->tmpname, "P");
00146        strcat(info->tmpname, pid_buf);
00147 
00148        if (*uniq)
00149               strcat(strcat(info->tmpname, "_"), uniq);
00150        strcat(info->tmpname, ".");
00151        strcat(info->tmpname, hostname);
00152        strcat(info->tmpname, len_buf);
00153 
00154        if (stat( info->tmpname, &stat_buf) == 0)
00155        {
00156               maildir_tmpcreate_free(info);
00157               errno=EAGAIN;
00158               return -1;
00159        }
00160 
00161        if (errno != ENOENT)
00162        {
00163               maildir_tmpcreate_free(info);
00164               if (errno == EAGAIN)
00165                      errno=EIO;
00166               return -1;
00167        }
00168 
00169        if ((fd=maildir_safeopen_stat(info->tmpname, O_CREAT|O_RDWR|O_TRUNC,
00170                                   info->openmode, &stat_buf)) < 0)
00171        {
00172               maildir_tmpcreate_free(info);
00173               return -1;
00174        }
00175 
00176        libmail_strh_dev_t(stat_buf.st_dev, dev_buf);
00177        libmail_strh_ino_t(stat_buf.st_ino, ino_buf);
00178 
00179        if (info->newname)
00180               free(info->newname);
00181 
00182        info->newname=malloc(strlen(info->tmpname)+strlen(ino_buf)+
00183                           strlen(dev_buf)+3);
00184 
00185        if (!info->newname)
00186        {
00187               maildir_tmpcreate_free(info);
00188               unlink(info->tmpname);
00189               close(fd);
00190               if (errno == EAGAIN)
00191                      errno=EIO;
00192               return -1;
00193        }
00194 
00195        strcpy(info->newname, maildir);
00196        strcat(info->newname, "/new/");
00197        strcat(info->newname, time_buf);
00198        strcat(info->newname, ".M");
00199        strcat(info->newname, usec_buf);
00200        strcat(info->newname, "P");
00201        strcat(info->newname, pid_buf);
00202        strcat(info->newname, "V");
00203        strcat(info->newname, dev_buf);
00204        strcat(info->newname, "I");
00205        strcat(info->newname, ino_buf);
00206        if (*uniq)
00207               strcat(strcat(info->newname, "_"), uniq);
00208        strcat(info->newname, ".");
00209        strcat(info->newname, hostname);
00210        strcat(info->newname, len_buf);
00211 
00212        return fd;
00213 }
00214 
00215 void maildir_tmpcreate_free(struct maildir_tmpcreate_info *info)
00216 {
00217        if (info->tmpname)
00218               free(info->tmpname);
00219        info->tmpname=NULL;
00220 
00221        if (info->newname)
00222               free(info->newname);
00223        info->newname=NULL;
00224 }
00225 
00226 int maildir_movetmpnew(const char *tmpname, const char *newname)
00227 {
00228        if (link(tmpname, newname) == 0)
00229        {
00230               unlink(tmpname);
00231               return 0;
00232        }
00233 
00234        if (errno != EXDEV)
00235               return -1;
00236 
00237        /* AFS? */
00238 
00239        return rename(tmpname, newname);
00240 }