1 # DP: From: Miquel van Smoorenburg <miquels@cistron.nl>
2 # DP: A patch that adds support for Maildir type mailboxes.
4 --- ./mailcheck.c.orig Wed Feb 4 21:30:33 1998
5 +++ ./mailcheck.c Sun Nov 14 15:35:07 1999
11 #include "bashtypes.h"
12 #include "posixstat.h"
13 +#include "posixdir.h"
15 # include <sys/param.h>
18 #include "mailcheck.h"
19 #include <tilde/tilde.h>
21 +#include "mailstat.c"
24 #define NOW ((time_t)time ((time_t *)0))
29 file = mailfiles[i]->name;
30 - if (stat (file, &finfo) == 0)
31 + if (mailstat (file, &finfo) == 0)
33 mailfiles[i]->access_time = finfo.st_atime;
34 mailfiles[i]->mod_time = finfo.st_mtime;
36 i = find_mail_file (filename);
39 - if (stat (filename, &finfo) == 0)
40 + if (mailstat (filename, &finfo) == 0)
42 mailfiles[i]->mod_time = finfo.st_mtime;
43 mailfiles[i]->access_time = finfo.st_atime;
45 file = mailfiles[i]->name;
46 mtime = mailfiles[i]->mod_time;
48 - if ((stat (file, &finfo) == 0) && (finfo.st_size > 0))
49 + if ((mailstat (file, &finfo) == 0) && (finfo.st_size > 0))
50 return (mtime != finfo.st_mtime);
54 file = mailfiles[i]->name;
55 atime = mailfiles[i]->access_time;
57 - if ((stat (file, &finfo) == 0) && (finfo.st_size > 0))
58 + if ((mailstat (file, &finfo) == 0) && (finfo.st_size > 0))
59 return (atime != finfo.st_atime);
63 file = mailfiles[i]->name;
64 size = mailfiles[i]->file_size;
66 - return ((stat (file, &finfo) == 0) && (finfo.st_size > size));
67 + return ((mailstat (file, &finfo) == 0) && (finfo.st_size > size));
70 /* Take an element from $MAILPATH and return the portion from
73 diff -ruN bash-2.01.1.b4/mailstat.c bash-2.01.1/mailstat.c
74 --- bash-2.01.1.b4/mailstat.c Thu Jan 1 01:00:00 1970
75 +++ bash-2.01.1/mailstat.c Wed Jun 2 12:05:04 1999
78 + * Stat a file. If it's a maildir, check all messages
79 + * in the maildir and present the grand total as a file.
80 + * The fields in the 'struct stat' are from the mail directory.
81 + * The following fields are emulated:
84 + * st_size total number of bytes in all files
85 + * st_blocks total number of messages
86 + * st_atime access time of newest file in maildir
87 + * st_mtime modify time of newest file in maildir
88 + * st_mode S_IFDIR changed to S_IFREG
90 + * This is good enough for most mail-checking applications.
93 +mailstat(char *path, struct stat *st)
97 + struct stat st_ret, st_tmp;
98 + static struct stat st_new_last, st_ret_last;
99 + char dir[PATH_MAX * 2];
100 + char file[PATH_MAX * 2];
102 + time_t atime = 0, mtime = 0;
104 + /* First see if it's a directory. */
105 + if ((i = stat(path, st)) != 0 || !S_ISDIR(st->st_mode))
107 + if (strlen(path) > sizeof(dir) - 5) {
108 + errno = ENAMETOOLONG;
113 + st_ret.st_nlink = 1;
114 + st_ret.st_size = 0;
115 + st_ret.st_blocks = 0;
116 + st_ret.st_mode &= ~S_IFDIR;
117 + st_ret.st_mode |= S_IFREG;
119 + /* See if cur/ is present */
120 + sprintf(dir, "%s/cur", path);
121 + if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
122 + st_ret.st_atime = st_tmp.st_atime;
124 + /* See if tmp/ is present */
125 + sprintf(dir, "%s/tmp", path);
126 + if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
127 + st_ret.st_mtime = st_tmp.st_mtime;
130 + sprintf(dir, "%s/new", path);
131 + if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
132 + st_ret.st_mtime = st_tmp.st_mtime;
134 + /* Optimization - if new/ didn't change, nothing else did. */
135 + if (st_tmp.st_dev == st_new_last.st_dev &&
136 + st_tmp.st_ino == st_new_last.st_ino &&
137 + st_tmp.st_atime == st_new_last.st_atime &&
138 + st_tmp.st_mtime == st_new_last.st_mtime) {
142 + st_new_last = st_tmp;
144 + /* Loop over new/ and cur/ */
145 + for (i = 0; i < 2; i++) {
146 + sprintf(dir, "%s/%s", path, i ? "cur" : "new");
147 + sprintf(file, "%s/", dir);
149 + if ((dd = opendir(dir)) == NULL)
151 + while ((fn = readdir(dd)) != NULL) {
152 + if (fn->d_name[0] == '.' ||
153 + strlen(fn->d_name) + l >= sizeof(file))
155 + strcpy(file + l, fn->d_name);
156 + if (stat(file, &st_tmp) != 0)
158 + st_ret.st_size += st_tmp.st_size;
159 + st_ret.st_blocks++;
160 + if (st_tmp.st_atime != st_tmp.st_mtime &&
161 + st_tmp.st_atime > atime)
162 + atime = st_tmp.st_atime;
163 + if (st_tmp.st_mtime > mtime)
164 + mtime = st_tmp.st_mtime;
169 + if (atime) st_ret.st_atime = atime;
170 + if (mtime) st_ret.st_mtime = mtime;
172 + *st = st_ret_last = st_ret;