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); }
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); }
int main(int argc, char **argv) { const char *dir; struct stat stat_buf; int auto_create = 0; int quota_warn_percent = -1; int i; const char *quota=NULL; for (i=1; i<argc; i++) { if (strcmp(argv[i], "-c") == 0) { auto_create = 1; continue; } if (strcmp(argv[i], "-w") == 0 && argc - i > 1) { quota_warn_percent = atoi(argv[i+1]); ++i; continue; } break; } if (i >= argc || quota_warn_percent < -1 || quota_warn_percent > 100) { fprintf(stderr, "Usage: %s [-c] [-w percent] maildir\n", argv[0]); exit(73); } dir=argv[i]; ++i; if (i < argc) quota=argv[i]; if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) && stat_buf.st_size > 0) { struct maildirsize info; int doquota=maildirquota_countfolder(dir); if (doquota && maildir_quota_add_start(dir, &info, stat_buf.st_size, 1, quota)) { if (quota_warn_percent >= 0) maildir_deliver_quota_warning(dir, quota_warn_percent); printf("Mail quota exceeded.\n"); exit(77); } deliver(0, dir, stat_buf.st_size, auto_create, quota_warn_percent, NULL, quota); if (doquota) maildir_quota_add_end(&info, stat_buf.st_size, 1); exit(0); } deliver(0, dir, 0, auto_create, quota_warn_percent, NULL, quota); exit(0); }