static int update_link(const char *curdir, const char *linkname, const char *linkvalue, const char *shareddir, const char *msgfilename, size_t msgfilenamelen) { char *p=malloc(strlen(shareddir)+sizeof("/cur/")+msgfilenamelen); char *q; int fd; struct maildir_tmpcreate_info createInfo; if (!p) { perror("malloc"); return (-1); } strcat(strcpy(p, shareddir), "/cur/"); q=p+strlen(p); memcpy(q, msgfilename, msgfilenamelen); q[msgfilenamelen]=0; if (linkvalue && strcmp(p, linkvalue) == 0) { /* the link is good */ free(p); return (0); } /* Ok, we want this to be an atomic operation. */ maildir_tmpcreate_init(&createInfo); createInfo.maildir=curdir; createInfo.uniq="relink"; createInfo.doordie=1; if ((fd=maildir_tmpcreate_fd(&createInfo)) < 0) return -1; close(fd); unlink(createInfo.tmpname); if (symlink(p, createInfo.tmpname) < 0 || rename(createInfo.tmpname, linkname) < 0) { perror(createInfo.tmpname); maildir_tmpcreate_free(&createInfo); return (-1); } maildir_tmpcreate_free(&createInfo); return (0); }
int maildir_filter_savemaildirfilter(struct maildirfilter *mf, const char *maildir, const char *from) { // by lfan, to support .qmail-user forward file char *p, *p2, *user; char *maildirpath; //const char *maildirpath=maildir_filter_config(maildir, "MAILDIR"); struct maildir_tmpcreate_info createInfo; int fd, rc; p=login_returnaddr(); p2=strdup(p); user=strtok(p2, "@"); p = malloc(strlen(user) + 12); sprintf( p, "./%s/Maildir", user ); free(p2); maildirpath=p; if (!maildirpath || !*maildirpath) { errno=EINVAL; return (-1); } maildir_tmpcreate_init(&createInfo); createInfo.maildir=maildir; createInfo.uniq="maildirfilter-tmp"; createInfo.doordie=1; if ((fd=maildir_tmpcreate_fd(&createInfo)) < 0) return -1; close(fd); unlink(createInfo.tmpname); strcat(strcpy(createInfo.newname, maildir), "/maildirfilter.tmp"); rc=maildir_filter_saverules(mf, createInfo.tmpname, maildir, maildirpath, from); if (rc == 0 && rename(createInfo.tmpname, createInfo.newname)) rc= -1; maildir_tmpcreate_free(&createInfo); free(p); return (rc); }
FILE *maildir_tmpcreate_fp(struct maildir_tmpcreate_info *info) { int fd=maildir_tmpcreate_fd(info); FILE *fp; if (fd < 0) return NULL; fp=fdopen(fd, "w+"); if (fp == NULL) { close(fd); return NULL; } return fp; }
static int create_db(struct dbobj *obj, const char *dir, char **dbname) { struct maildir_tmpcreate_info createInfo; maildir_tmpcreate_init(&createInfo); createInfo.maildir=dir; createInfo.uniq="sync"; createInfo.doordie=1; { int fd; fd=maildir_tmpcreate_fd(&createInfo); if (fd < 0) { perror(dir); return -1; } close(fd); dbobj_init(obj); if (dbobj_open(obj, createInfo.tmpname, "N") < 0) { perror(createInfo.tmpname); unlink(createInfo.tmpname); maildir_tmpcreate_free(&createInfo); return (-1); } } *dbname=createInfo.tmpname; createInfo.tmpname=NULL; maildir_tmpcreate_free(&createInfo); return (0); }
int Maildir::MaildirOpen(const char *dir, Mio &file, off_t s) { Buffer buf; struct maildirsize quotainfo; const char *quotap; Buffer quotabuf; quotabuf="MAILDIRQUOTA"; /* Reuse a convenient buffer */ quotabuf= *GetVar(quotabuf); quotabuf += '\0'; quotap=quotabuf; if (!*quotap) quotap=NULL; MaildirAbort(); AlarmTimer abort_timer; static long counter=0; buf.set(counter++); buf += '\0'; struct maildir_tmpcreate_info createInfo; maildir_tmpcreate_init(&createInfo); createInfo.maildir=dir; createInfo.uniq=(const char *)buf; createInfo.msgsize=s; createInfo.openmode=0666; abort_timer.Set( 24 * 60 * 60 ); while (!abort_timer.Expired()) { Buffer name_buf; name_buf="UMASK"; const char *um=GetVarStr(name_buf); unsigned int umask_val=077; sscanf(um, "%o", &umask_val); umask_val=umask(umask_val); int f=maildir_tmpcreate_fd(&createInfo); umask(umask_val); if (f >= 0) { Buffer b; b="FLAGS"; const char *flags=GetVarStr(b); tmpname=createInfo.tmpname; tmpname += '\0'; if (flags) { const char *p=flags; while (*p) { if (strchr("DRSF", *p) == NULL) { f=0; break; } ++p; } } if (flags && *flags) { newname=createInfo.curname; newname += ':'; newname += '2'; newname += ','; newname += flags; } else { newname=createInfo.newname; } newname += '\0'; maildir_tmpcreate_free(&createInfo); file.fd(f); is_open=1; maildirRoot=dir; maildirRoot += '\0'; if (maildir_quota_add_start(dir, "ainfo, s, 1, quotap)) { file.fd(-1); unlink( (const char *)tmpname ); is_open=0; maildir_deliver_quota_warning(dir, quota_warn_percent, quota_warn_message); merr << "maildrop: maildir over quota.\n"; return (-1); } maildir_quota_add_end("ainfo, s, 1); return (0); } if (errno != EAGAIN) { merr << "maildrop: " << dir << ": " << strerror(errno) << "\n"; return -1; } AlarmSleep try_again(2); } merr << "maildrop: time out on maildir directory.\n"; return (-1); }
static int newmsgs(const char *cur, const char *shared, struct dbobj *obj) { char *key, *val; size_t keylen, vallen; int fd; struct maildir_tmpcreate_info createInfo; maildir_tmpcreate_init(&createInfo); createInfo.maildir=cur; createInfo.uniq="newlink"; createInfo.doordie=1; if ((fd=maildir_tmpcreate_fd(&createInfo)) < 0) return -1; close(fd); unlink(createInfo.tmpname); for (key=dbobj_firstkey(obj, &keylen, &val, &vallen); key; key=dbobj_nextkey(obj, &keylen, &val, &vallen)) { char *slink=malloc(strlen(shared)+sizeof("/cur/")+vallen); char *q; if (!slink) { free(val); maildir_tmpcreate_free(&createInfo); return (-1); } strcat(strcpy(slink, shared), "/cur/"); q=slink+strlen(slink); memcpy(q, val, vallen); q[vallen]=0; free(val); if (symlink(slink, createInfo.tmpname)) { perror(createInfo.tmpname); free(slink); maildir_tmpcreate_free(&createInfo); return (-1); } free(slink); slink=malloc(strlen(cur)+sizeof("/new/" MDIRSEP "2,")+keylen); if (!slink) { perror("malloc"); maildir_tmpcreate_free(&createInfo); return (-1); } strcat(strcpy(slink, cur), "/new/"); q=slink+strlen(slink); memcpy(q, key, keylen); strcpy(q+keylen, MDIRSEP "2,"); if (rename(createInfo.tmpname, slink)) { free(slink); maildir_tmpcreate_free(&createInfo); return (-1); } free(slink); } maildir_tmpcreate_free(&createInfo); return (0); }
static long deliver(int fdin, const char *dir, long s, int auto_create, int quota_warn_percent, const char *pfix, const char *newquota) { struct maildir_tmpcreate_info createInfo; char buf[BUFSIZ]; int n; long ss=0; int fd; maildir_tmpcreate_init(&createInfo); createInfo.maildir=dir; createInfo.uniq=pfix; createInfo.msgsize=s; createInfo.doordie=1; while ((fd=maildir_tmpcreate_fd(&createInfo)) < 0) { if (errno == ENOENT && auto_create && maildir_mkdir(dir) == 0) { auto_create=0; continue; } perror(dir); exit(EX_TEMPFAIL); } while ((n=read(fdin, buf, sizeof(buf))) > 0) { char *p=buf; ss += n; while (n) { int l; if ((l=write(fd, p, n)) < 0) { close(fd); unlink(createInfo.tmpname); perror(createInfo.tmpname); exit(EX_IOERR); } p += l; n -= l; } } close(fd); if (n < 0) { unlink(createInfo.tmpname); perror(createInfo.tmpname); exit(EX_IOERR); } if (s != ss) { char *qq; struct maildirsize info; if (s) *strrchr(createInfo.newname, ',')=0; /* Zap incorrect size */ qq=malloc(strlen(createInfo.newname)+100); if (!qq) { unlink(createInfo.tmpname); perror(createInfo.tmpname); exit(EX_OSERR); } sprintf(qq, "%s,S=%ld", createInfo.newname, ss-s); free(createInfo.newname); createInfo.newname=qq; if (maildirquota_countfolder(dir)) { if (maildir_quota_add_start(dir, &info, ss-s, 1, newquota)) { unlink(createInfo.tmpname); printf("Mail quota exceeded.\n"); exit(EX_NOPERM); } maildir_quota_add_end(&info, ss-s, 1); } } if (maildir_movetmpnew(createInfo.tmpname, createInfo.newname)) { unlink(createInfo.tmpname); perror(createInfo.tmpname); exit(EX_IOERR); } maildir_tmpcreate_free(&createInfo); if (quota_warn_percent >= 0) maildir_deliver_quota_warning(dir, quota_warn_percent); return (ss); }