📄 maildirquota.c
字号:
if (maildirsize_nlines == 1 && tm < stat_buf.st_mtime + 15*60) return (n); } maxtime=0; maildirsize_size=0; maildirsize_cnt=0; if (countcurnew(dir, &maxtime, &maildirsize_size, &maildirsize_cnt)) { free(checkfolder); return (-1); } dirp=opendir(dir); while (dirp && (de=readdir(dirp)) != 0) { if (countsubdir(dir, de->d_name, &maxtime, &maildirsize_size, &maildirsize_cnt)) { free(checkfolder); closedir(dirp); return (-1); } } if (dirp) {#if CLOSEDIR_VOID closedir(dirp);#else if (closedir(dirp)) { free(checkfolder); return (-1); }#endif } newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd); if (!newmaildirsizename) { free(checkfolder); return (-1); } *maildirsize_fdptr=maildirsize_fd; if (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size, maildirsize_cnt, 1)) { free(newmaildirsizename); unlink(newmaildirsizename); close(maildirsize_fd); *maildirsize_fdptr= -1; free(checkfolder); return (-1); } strcat(strcpy(checkfolder, dir), "/maildirsize"); if (rename(newmaildirsizename, checkfolder)) { free(checkfolder); unlink(newmaildirsizename); close(maildirsize_fd); *maildirsize_fdptr= -1; } free(checkfolder); free(newmaildirsizename); tm=0; if (statcurnew(dir, &tm)) { close(maildirsize_fd); *maildirsize_fdptr= -1; return (-1); } dirp=opendir(dir); while (dirp && (de=readdir(dirp)) != 0) { if (statsubdir(dir, de->d_name, &tm)) { close(maildirsize_fd); *maildirsize_fdptr= -1; closedir(dirp); return (-1); } } if (dirp) {#if CLOSEDIR_VOID closedir(dirp);#else if (closedir(dirp)) { close(maildirsize_fd); *maildirsize_fdptr= -1; return (-1); }#endif } if (tm != maxtime) /* Race condition, someone changed something */ { errno=EAGAIN; return (-1); } return (qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt, quota_type, percentage));}static int maildir_addquota(const char *dir, int maildirsize_fd, const char *quota_type, long maildirsize_size, int maildirsize_cnt){ if (!quota_type || !*quota_type) return (0); return (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size, maildirsize_cnt, 0));}static int doaddquota(const char *dir, int maildirsize_fd, const char *quota_type, long maildirsize_size, int maildirsize_cnt, int isnew){union { char buf[100]; struct stat stat_buf; } u; /* Scrooge */char *newname2=0;char *newmaildirsizename=0;struct iovec iov[3];int niov;struct iovec *p;int n; niov=0; if ( maildirsize_fd < 0) { newname2=(char *)malloc(strlen(dir)+sizeof("/maildirfolder")); if (!newname2) return (-1); strcat(strcpy(newname2, dir), "/maildirfolder"); if (stat(newname2, &u.stat_buf) == 0) { strcat(strcpy(newname2, dir), "/.."); n=doaddquota(newname2, maildirsize_fd, quota_type, maildirsize_size, maildirsize_cnt, isnew); free(newname2); return (n); } strcat(strcpy(newname2, dir), "/maildirsize"); if ((maildirsize_fd=maildir_safeopen(newname2, O_RDWR|O_APPEND, 0644)) < 0) { newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd); if (!newmaildirsizename) { free(newname2); return (-1); } maildirsize_fd=maildir_safeopen(newmaildirsizename, O_CREAT|O_RDWR|O_APPEND, 0644); if (maildirsize_fd < 0) { free(newname2); return (-1); } isnew=1; } } if (isnew) { iov[0].iov_base=(void *)quota_type; iov[0].iov_len=strlen(quota_type); iov[1].iov_base="\n"; iov[1].iov_len=1; niov=2; } sprintf(u.buf, "%ld %d\n", maildirsize_size, maildirsize_cnt); iov[niov].iov_base=u.buf; iov[niov].iov_len=strlen(u.buf); p=iov; ++niov; n=0; while (niov) { if (n) { if (n < p->iov_len) { p->iov_base= ((char *)p->iov_base + n); p->iov_len -= n; } else { n -= p->iov_len; ++p; --niov; continue; } } n=writev( maildirsize_fd, p, niov); if (n <= 0) { if (newname2) { close(maildirsize_fd); free(newname2); } return (-1); } } if (newname2) { close(maildirsize_fd); if (newmaildirsizename) { rename(newmaildirsizename, newname2); free(newmaildirsizename); } free(newname2); } return (0);}/* New maildirsize is built in the tmp subdirectory */static char *makenewmaildirsizename(const char *dir, int *fd){char hostname[256];struct stat stat_buf;time_t t;char *p;int i; hostname[0]=0; hostname[sizeof(hostname)-1]=0; gethostname(hostname, sizeof(hostname)-1); p=(char *)malloc(strlen(dir)+strlen(hostname)+130); if (!p) return (0); /* do not hang forever */ for (i=0;i<3;++i) { char tbuf[NUMBUFSIZE]; char pbuf[NUMBUFSIZE]; time(&t); strcat(strcpy(p, dir), "/tmp/"); sprintf(p+strlen(p), "%s.%s_NeWmAiLdIrSiZe.%s", str_time_t(t, tbuf), str_pid_t(getpid(), pbuf), hostname); if (stat( (const char *)p, &stat_buf) < 0 && (*fd=maildir_safeopen(p, O_CREAT|O_RDWR|O_APPEND, 0644)) >= 0) break; usleep(100); } return (p);}static int statcurnew(const char *dir, time_t *maxtimestamp){char *p=(char *)malloc(strlen(dir)+5);struct stat stat_buf; if (!p) return (-1); strcat(strcpy(p, dir), "/cur"); if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp) *maxtimestamp=stat_buf.st_mtime; strcat(strcpy(p, dir), "/new"); if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp) *maxtimestamp=stat_buf.st_mtime; free(p); return (0);}static int statsubdir(const char *dir, const char *subdir, time_t *maxtime){char *p;int n; if ( *subdir != '.' || strcmp(subdir, ".") == 0 || strcmp(subdir, "..") == 0 || strcmp(subdir, ".Trash") == 0) return (0); p=(char *)malloc(strlen(dir)+strlen(subdir)+2); if (!p) return (-1); strcat(strcat(strcpy(p, dir), "/"), subdir); n=statcurnew(p, maxtime); free(p); return (n);}static int countcurnew(const char *dir, time_t *maxtime, off_t *sizep, unsigned *cntp){char *p=(char *)malloc(strlen(dir)+5);int n; if (!p) return (-1); strcat(strcpy(p, dir), "/new"); n=docount(p, maxtime, sizep, cntp); if (n == 0) { strcat(strcpy(p, dir), "/cur"); n=docount(p, maxtime, sizep, cntp); } free(p); return (n);}static int countsubdir(const char *dir, const char *subdir, time_t *maxtime, off_t *sizep, unsigned *cntp){char *p;int n; if ( *subdir != '.' || strcmp(subdir, ".") == 0 || strcmp(subdir, "..") == 0 || strcmp(subdir, ".Trash") == 0) return (0); p=(char *)malloc(strlen(dir)+strlen(subdir)+2); if (!p) return (2); strcat(strcat(strcpy(p, dir), "/"), subdir); n=countcurnew(p, maxtime, sizep, cntp); free(p); return (n);}static int docount(const char *dir, time_t *dirstamp, off_t *sizep, unsigned *cntp){struct stat stat_buf;char *p;DIR *dirp;struct dirent *de;unsigned long s; if (stat(dir, &stat_buf)) return (0); /* Ignore */ if (stat_buf.st_mtime > *dirstamp) *dirstamp=stat_buf.st_mtime; if ((dirp=opendir(dir)) == 0) return (0); while ((de=readdir(dirp)) != 0) { const char *n=de->d_name; if (*n == '.') continue; /* PATCH - do not count msgs marked as deleted */ for ( ; *n; n++) { if (n[0] != ':' || n[1] != '2' || n[2] != ',') continue; n += 3; while (*n >= 'A' && *n <= 'Z') { if (*n == 'T') break; ++n; } break; } if (*n == 'T') continue; n=de->d_name; if (maildir_parsequota(n, &s) == 0) stat_buf.st_size=s; else { p=(char *)malloc(strlen(dir)+strlen(n)+2); if (!p) { closedir(dirp); return (-1); } strcat(strcat(strcpy(p, dir), "/"), n); if (stat(p, &stat_buf)) { free(p); continue; } free(p); } *sizep += stat_buf.st_size; ++*cntp; }#if CLOSEDIR_VOID closedir(dirp);#else if (closedir(dirp)) return (-1);#endif return (0);}static int maildir_safeopen(const char *path, int mode, int perm){struct stat stat1, stat2;int fd=open(path, mode#ifdef O_NONBLOCK | O_NONBLOCK#else | O_NDELAY#endif , perm); if (fd < 0) return (fd); if (fcntl(fd, F_SETFL, (mode & O_APPEND)) || fstat(fd, &stat1) || lstat(path, &stat2)) { close(fd); return (-1); } if (stat1.st_dev != stat2.st_dev || stat1.st_ino != stat2.st_ino) { close(fd); errno=ENOENT; return (-1); } return (fd);}static char *str_pid_t(pid_t t, char *arg){char buf[NUMBUFSIZE];char *p=buf+sizeof(buf)-1; *p=0; do { *--p= '0' + (t % 10); t=t / 10; } while(t); return (strcpy(arg, p));}static char *str_time_t(time_t t, char *arg){char buf[NUMBUFSIZE];char *p=buf+sizeof(buf)-1; *p=0; do { *--p= '0' + (t % 10); t=t / 10; } while(t); return (strcpy(arg, p));}static int maildir_parsequota(const char *n, unsigned long *s){const char *o;int yes; if ((o=strrchr(n, '/')) == 0) o=n; for (; *o; o++) if (*o == ':') break; yes=0; for ( ; o >= n; --o) { if (*o == '/') break; if (*o == ',' && o[1] == 'S' && o[2] == '=') { yes=1; o += 3; break; } } if (yes) { *s=0; while (*o >= '0' && *o <= '9') *s= *s*10 + (*o++ - '0'); return (0); } return (-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -