Link Here
|
|
|
1 |
diff -ruN Makefile Makefile |
2 |
--- Makefile Wed Aug 6 17:05:13 2003 |
3 |
+++ Makefile Wed Aug 6 17:09:48 2003 |
4 |
@@ -890,6 +890,38 @@ |
5 |
readwrite.h open.h headerbody.h maildir.h strerr.h |
6 |
./compile maildirwatch.c |
7 |
|
8 |
+maildirgetquota.o: \ |
9 |
+compile maildirgetquota.c maildirgetquota.h maildirmisc.h |
10 |
+ ./compile maildirgetquota.c |
11 |
+ |
12 |
+maildirflags.o: \ |
13 |
+compile maildirflags.c |
14 |
+ ./compile maildirflags.c |
15 |
+ |
16 |
+maildiropen.o: \ |
17 |
+compile maildiropen.c maildirmisc.h |
18 |
+ ./compile maildiropen.c |
19 |
+ |
20 |
+maildirparsequota.o: \ |
21 |
+compile maildirparsequota.c |
22 |
+ ./compile maildirparsequota.c |
23 |
+ |
24 |
+maildirquota.o: \ |
25 |
+compile maildirquota.c maildirquota.h maildirmisc.h numlib.h |
26 |
+ ./compile maildirquota.c |
27 |
+ |
28 |
+overmaildirquota.o: \ |
29 |
+compile overmaildirquota.c |
30 |
+ ./compile overmaildirquota.c |
31 |
+ |
32 |
+strtimet.o: \ |
33 |
+compile strtimet.c |
34 |
+ ./compile strtimet.c |
35 |
+ |
36 |
+strpidt.o: \ |
37 |
+compile strpidt.c |
38 |
+ ./compile strpidt.c |
39 |
+ |
40 |
mailsubj: \ |
41 |
warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split |
42 |
cat warn-auto.sh mailsubj.sh \ |
43 |
@@ -1174,12 +1206,15 @@ |
44 |
load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \ |
45 |
slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \ |
46 |
wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ |
47 |
-fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib |
48 |
+fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib maildirquota.o \ |
49 |
+maildirgetquota.o maildiropen.o maildirparsequota.o overmaildirquota.o \ |
50 |
+strtimet.o strpidt.o |
51 |
./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \ |
52 |
slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \ |
53 |
lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \ |
54 |
substdio.a error.a str.a fs.a datetime.a auto_qmail.o \ |
55 |
- auto_patrn.o `cat socket.lib` |
56 |
+ auto_patrn.o `cat socket.lib` maildirquota.o maildirgetquota.o \ |
57 |
+ maildiropen.o maildirparsequota.o overmaildirquota.o strtimet.o strpidt.o |
58 |
|
59 |
qmail-local.0: \ |
60 |
qmail-local.8 |
61 |
@@ -1269,11 +1304,13 @@ |
62 |
qmail-pop3d: \ |
63 |
load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \ |
64 |
maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \ |
65 |
-stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib |
66 |
+stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib maildirquota.o \ |
67 |
+maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o |
68 |
./load qmail-pop3d commands.o case.a timeoutread.o \ |
69 |
timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \ |
70 |
open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \ |
71 |
- fs.a `cat socket.lib` |
72 |
+ fs.a `cat socket.lib` maildirquota.o maildirgetquota.o \ |
73 |
+ maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o |
74 |
|
75 |
qmail-pop3d.0: \ |
76 |
qmail-pop3d.8 |
77 |
diff -ruN TARGETS TARGETS |
78 |
--- TARGETS Wed Aug 6 17:05:13 2003 |
79 |
+++ TARGETS Wed Aug 6 17:09:48 2003 |
80 |
@@ -15,6 +15,14 @@ |
81 |
slurpclose.o |
82 |
make-makelib |
83 |
makelib |
84 |
+maildirflags.o |
85 |
+maildirparsequota.o |
86 |
+maildiropen.o |
87 |
+maildirgetquota.o |
88 |
+maildirquota.o |
89 |
+overmaildirquota.o |
90 |
+strtimet.o |
91 |
+strpidt.o |
92 |
case_diffb.o |
93 |
case_diffs.o |
94 |
case_lowerb.o |
95 |
diff -ruN maildirflags.c maildirflags.c |
96 |
--- maildirflags.c Thu Jan 1 01:00:00 1970 |
97 |
+++ maildirflags.c Wed Aug 6 17:09:48 2003 |
98 |
@@ -0,0 +1,23 @@ |
99 |
+/* |
100 |
+** Copyright 2000 Double Precision, Inc. |
101 |
+** See COPYING for distribution information. |
102 |
+*/ |
103 |
+ |
104 |
+#include <sys/types.h> |
105 |
+#include <string.h> |
106 |
+ |
107 |
+static const char rcsid[]="$Id: maildirflags.c,v 1.1 2000/10/07 01:10:19 mrsam Exp $"; |
108 |
+ |
109 |
+int maildir_hasflag(const char *filename, char flag) |
110 |
+{ |
111 |
+ const char *p=strrchr(filename, '/'); |
112 |
+ |
113 |
+ if (p) |
114 |
+ filename=p+1; |
115 |
+ |
116 |
+ p=strrchr(p, ':'); |
117 |
+ if (p && strncmp(p, ":2,", 3) == 0 && |
118 |
+ strchr(p+3, flag)) |
119 |
+ return (1); |
120 |
+ return (0); |
121 |
+} |
122 |
diff -ruN maildirgetquota.c maildirgetquota.c |
123 |
--- maildirgetquota.c Thu Jan 1 01:00:00 1970 |
124 |
+++ maildirgetquota.c Wed Aug 6 17:09:48 2003 |
125 |
@@ -0,0 +1,50 @@ |
126 |
+/* |
127 |
+** Copyright 1998 - 2000 Double Precision, Inc. |
128 |
+** See COPYING for distribution information. |
129 |
+*/ |
130 |
+ |
131 |
+#include "maildirgetquota.h" |
132 |
+#include "maildirmisc.h" |
133 |
+#if HAVE_UNISTD_H |
134 |
+#include <unistd.h> |
135 |
+#endif |
136 |
+#include <stdlib.h> |
137 |
+#include <string.h> |
138 |
+#include <fcntl.h> |
139 |
+#include <sys/types.h> |
140 |
+#include <sys/stat.h> |
141 |
+ |
142 |
+int maildir_getquota(const char *dir, char buf[QUOTABUFSIZE]) |
143 |
+{ |
144 |
+char *p; |
145 |
+struct stat stat_buf; |
146 |
+int n; |
147 |
+int l; |
148 |
+ |
149 |
+ p=(char *)malloc(strlen(dir)+sizeof("/maildirfolder")); |
150 |
+ if (!p) return (-1); |
151 |
+ |
152 |
+ strcat(strcpy(p, dir), "/maildirfolder"); |
153 |
+ if (stat(p, &stat_buf) == 0) |
154 |
+ { |
155 |
+ strcat(strcpy(p, dir), "/.."); |
156 |
+ n=maildir_getquota(p, buf); |
157 |
+ free(p); |
158 |
+ return (n); |
159 |
+ } |
160 |
+ |
161 |
+ strcat(strcpy(p, dir), "/maildirsize"); |
162 |
+ n=maildir_safeopen(p, O_RDONLY, 0); |
163 |
+ free(p); |
164 |
+ if (n < 0) return (n); |
165 |
+ if ((l=read(n, buf, QUOTABUFSIZE-1)) < 0) |
166 |
+ { |
167 |
+ close(n); |
168 |
+ return (-1); |
169 |
+ } |
170 |
+ close(n); |
171 |
+ for (n=0; n<l; n++) |
172 |
+ if (buf[n] == '\n') break; |
173 |
+ buf[n]=0; |
174 |
+ return (0); |
175 |
+} |
176 |
diff -ruN maildirgetquota.h maildirgetquota.h |
177 |
--- maildirgetquota.h Thu Jan 1 01:00:00 1970 |
178 |
+++ maildirgetquota.h Wed Aug 6 17:09:48 2003 |
179 |
@@ -0,0 +1,30 @@ |
180 |
+#ifndef maildirgetquota_h |
181 |
+#define maildirgetquota_h |
182 |
+ |
183 |
+/* |
184 |
+** Copyright 1998 - 1999 Double Precision, Inc. |
185 |
+** See COPYING for distribution information. |
186 |
+*/ |
187 |
+ |
188 |
+#if HAVE_CONFIG_H |
189 |
+#include "config.h" |
190 |
+#endif |
191 |
+ |
192 |
+#include <sys/types.h> |
193 |
+#include <stdio.h> |
194 |
+ |
195 |
+#ifdef __cplusplus |
196 |
+extern "C" { |
197 |
+#endif |
198 |
+ |
199 |
+static const char maildirgetquota_h_rcsid[]="$Id: maildirgetquota.h,v 1.5 1999/12/06 13:21:05 mrsam Exp $"; |
200 |
+ |
201 |
+#define QUOTABUFSIZE 256 |
202 |
+ |
203 |
+int maildir_getquota(const char *, char [QUOTABUFSIZE]); |
204 |
+ |
205 |
+#ifdef __cplusplus |
206 |
+} |
207 |
+#endif |
208 |
+ |
209 |
+#endif |
210 |
diff -ruN maildirmisc.h maildirmisc.h |
211 |
--- maildirmisc.h Thu Jan 1 01:00:00 1970 |
212 |
+++ maildirmisc.h Wed Aug 6 17:09:48 2003 |
213 |
@@ -0,0 +1,145 @@ |
214 |
+#ifndef maildirmisc_h |
215 |
+#define maildirmisc_h |
216 |
+ |
217 |
+/* |
218 |
+** Copyright 2000 Double Precision, Inc. |
219 |
+** See COPYING for distribution information. |
220 |
+*/ |
221 |
+ |
222 |
+#if HAVE_CONFIG_H |
223 |
+#include "config.h" |
224 |
+#endif |
225 |
+ |
226 |
+#ifdef __cplusplus |
227 |
+extern "C" { |
228 |
+#endif |
229 |
+ |
230 |
+static const char maildirmisc_h_rcsid[]="$Id: maildirmisc.h,v 1.8 2000/12/25 17:33:06 mrsam Exp $"; |
231 |
+ |
232 |
+/* |
233 |
+** |
234 |
+** Miscellaneous maildir-related code |
235 |
+** |
236 |
+*/ |
237 |
+ |
238 |
+/* Some special folders */ |
239 |
+ |
240 |
+#define INBOX "INBOX" |
241 |
+#define DRAFTS "Drafts" |
242 |
+#define SENT "Sent" |
243 |
+#define TRASH "Trash" |
244 |
+ |
245 |
+#define SHAREDSUBDIR "shared-folders" |
246 |
+ |
247 |
+char *maildir_folderdir(const char *, /* maildir */ |
248 |
+ const char *); /* folder name */ |
249 |
+ /* Returns the directory corresponding to foldername (foldername is |
250 |
+ ** checked to make sure that it's a valid name, else we set errno |
251 |
+ ** to EINVAL, and return (0). |
252 |
+ */ |
253 |
+ |
254 |
+char *maildir_filename(const char *, /* maildir */ |
255 |
+ const char *, /* folder */ |
256 |
+ const char *); /* filename */ |
257 |
+ /* |
258 |
+ ** Builds the filename to this message, suitable for opening. |
259 |
+ ** If the file doesn't appear to be there, search the maildir to |
260 |
+ ** see if someone changed the flags, and return the current filename. |
261 |
+ */ |
262 |
+ |
263 |
+int maildir_safeopen(const char *, /* filename */ |
264 |
+ int, /* mode */ |
265 |
+ int); /* perm */ |
266 |
+ |
267 |
+/* |
268 |
+** Same arguments as open(). When we're accessing a shared maildir, |
269 |
+** prevent someone from playing cute and dumping a bunch of symlinks |
270 |
+** in there. This function will open the indicate file only if the |
271 |
+** last component is not a symlink. |
272 |
+** This is implemented by opening the file with O_NONBLOCK (to prevent |
273 |
+** a DOS attack of someone pointing the symlink to a pipe, causing |
274 |
+** the open to hang), clearing O_NONBLOCK, then stat-int the file |
275 |
+** descriptor, lstating the filename, and making sure that dev/ino |
276 |
+** match. |
277 |
+*/ |
278 |
+ |
279 |
+int maildir_semisafeopen(const char *, /* filename */ |
280 |
+ int, /* mode */ |
281 |
+ int); /* perm */ |
282 |
+ |
283 |
+/* |
284 |
+** Same thing, except that we allow ONE level of soft link indirection, |
285 |
+** because we're reading from our own maildir, which points to the |
286 |
+** message in the sharable maildir. |
287 |
+*/ |
288 |
+ |
289 |
+int maildir_mkdir(const char *); /* directory */ |
290 |
+/* |
291 |
+** Create maildir including all subdirectories in the path (like mkdir -p) |
292 |
+*/ |
293 |
+ |
294 |
+void maildir_purgetmp(const char *); /* maildir */ |
295 |
+ /* purges old stuff out of tmp */ |
296 |
+ |
297 |
+void maildir_purge(const char *, /* directory */ |
298 |
+ unsigned); /* time_t to purge */ |
299 |
+ |
300 |
+void maildir_getnew(const char *, /* maildir */ |
301 |
+ const char *); /* folder */ |
302 |
+ /* move messages from new to cur */ |
303 |
+ |
304 |
+int maildir_deletefolder(const char *, /* maildir */ |
305 |
+ const char *); /* folder */ |
306 |
+ /* deletes a folder */ |
307 |
+ |
308 |
+int maildir_mddelete(const char *); /* delete a maildir folder by path */ |
309 |
+ |
310 |
+void maildir_list_sharable(const char *, /* maildir */ |
311 |
+ void (*)(const char *, void *), /* callback function */ |
312 |
+ void *); /* 2nd arg to callback func */ |
313 |
+ /* list sharable folders */ |
314 |
+ |
315 |
+int maildir_shared_subscribe(const char *, /* maildir */ |
316 |
+ const char *); /* folder */ |
317 |
+ /* subscribe to a shared folder */ |
318 |
+ |
319 |
+void maildir_list_shared(const char *, /* maildir */ |
320 |
+ void (*)(const char *, void *), /* callback function */ |
321 |
+ void *); /* 2nd arg to the callback func */ |
322 |
+ /* list subscribed folders */ |
323 |
+ |
324 |
+int maildir_shared_unsubscribe(const char *, /* maildir */ |
325 |
+ const char *); /* folder */ |
326 |
+ /* unsubscribe from a shared folder */ |
327 |
+ |
328 |
+char *maildir_shareddir(const char *, /* maildir */ |
329 |
+ const char *); /* folder */ |
330 |
+ /* |
331 |
+ ** Validate and return a path to a shared folder. folderdir must be |
332 |
+ ** a name of a valid shared folder. |
333 |
+ */ |
334 |
+ |
335 |
+void maildir_shared_sync(const char *); /* maildir */ |
336 |
+ /* "sync" the shared folder */ |
337 |
+ |
338 |
+int maildir_sharedisro(const char *); /* maildir */ |
339 |
+ /* maildir is a shared read-only folder */ |
340 |
+ |
341 |
+int maildir_unlinksharedmsg(const char *); /* filename */ |
342 |
+ /* Remove a message from a shared folder */ |
343 |
+ |
344 |
+/* Internal function that reads a symlink */ |
345 |
+ |
346 |
+char *maildir_getlink(const char *); |
347 |
+ |
348 |
+ /* Determine whether the maildir filename has a certain flag */ |
349 |
+ |
350 |
+int maildir_hasflag(const char *filename, char); |
351 |
+ |
352 |
+#define MAILDIR_DELETED(f) maildir_hasflag((f), 'T') |
353 |
+ |
354 |
+#ifdef __cplusplus |
355 |
+} |
356 |
+#endif |
357 |
+ |
358 |
+#endif |
359 |
diff -ruN maildiropen.c maildiropen.c |
360 |
--- maildiropen.c Thu Jan 1 01:00:00 1970 |
361 |
+++ maildiropen.c Wed Aug 6 17:09:48 2003 |
362 |
@@ -0,0 +1,133 @@ |
363 |
+/* |
364 |
+** Copyright 2000 Double Precision, Inc. |
365 |
+** See COPYING for distribution information. |
366 |
+*/ |
367 |
+ |
368 |
+#if HAVE_CONFIG_H |
369 |
+#include "config.h" |
370 |
+#endif |
371 |
+ |
372 |
+#include <sys/types.h> |
373 |
+#include <sys/stat.h> |
374 |
+#include <string.h> |
375 |
+#include <stdlib.h> |
376 |
+#include <time.h> |
377 |
+#if HAVE_UNISTD_H |
378 |
+#include <unistd.h> |
379 |
+#endif |
380 |
+#include <stdio.h> |
381 |
+#include <ctype.h> |
382 |
+#include <errno.h> |
383 |
+#include <fcntl.h> |
384 |
+ |
385 |
+#include "maildirmisc.h" |
386 |
+ |
387 |
+static const char rcsid[]="$Id: maildiropen.c,v 1.7 2000/12/10 04:43:44 mrsam Exp $"; |
388 |
+ |
389 |
+char *maildir_getlink(const char *filename) |
390 |
+{ |
391 |
+#if HAVE_READLINK |
392 |
+size_t bufsiz; |
393 |
+char *buf; |
394 |
+ |
395 |
+ bufsiz=0; |
396 |
+ buf=0; |
397 |
+ |
398 |
+ for (;;) |
399 |
+ { |
400 |
+ int n; |
401 |
+ |
402 |
+ if (buf) free(buf); |
403 |
+ bufsiz += 256; |
404 |
+ if ((buf=malloc(bufsiz)) == 0) |
405 |
+ { |
406 |
+ perror("malloc"); |
407 |
+ return (0); |
408 |
+ } |
409 |
+ if ((n=readlink(filename, buf, bufsiz)) < 0) |
410 |
+ { |
411 |
+ free(buf); |
412 |
+ return (0); |
413 |
+ } |
414 |
+ if (n < bufsiz) |
415 |
+ { |
416 |
+ buf[n]=0; |
417 |
+ break; |
418 |
+ } |
419 |
+ } |
420 |
+ return (buf); |
421 |
+#else |
422 |
+ return (0); |
423 |
+#endif |
424 |
+} |
425 |
+ |
426 |
+int maildir_semisafeopen(const char *path, int mode, int perm) |
427 |
+{ |
428 |
+ |
429 |
+#if HAVE_READLINK |
430 |
+ |
431 |
+char *l=maildir_getlink(path); |
432 |
+ |
433 |
+ if (l) |
434 |
+ { |
435 |
+ int f; |
436 |
+ |
437 |
+ if (*l != '/') |
438 |
+ { |
439 |
+ char *q=malloc(strlen(path)+strlen(l)+2); |
440 |
+ char *s; |
441 |
+ |
442 |
+ if (!q) |
443 |
+ { |
444 |
+ free(l); |
445 |
+ return (-1); |
446 |
+ } |
447 |
+ |
448 |
+ strcpy(q, path); |
449 |
+ if ((s=strchr(q, '/')) != 0) |
450 |
+ s[1]=0; |
451 |
+ else *q=0; |
452 |
+ strcat(q, l); |
453 |
+ free(l); |
454 |
+ l=q; |
455 |
+ } |
456 |
+ |
457 |
+ f=maildir_safeopen(l, mode, perm); |
458 |
+ |
459 |
+ free(l); |
460 |
+ return (f); |
461 |
+ } |
462 |
+#endif |
463 |
+ |
464 |
+ return (maildir_safeopen(path, mode, perm)); |
465 |
+} |
466 |
+ |
467 |
+int maildir_safeopen(const char *path, int mode, int perm) |
468 |
+{ |
469 |
+struct stat stat1, stat2; |
470 |
+ |
471 |
+int fd=open(path, mode |
472 |
+#ifdef O_NONBLOCK |
473 |
+ | O_NONBLOCK |
474 |
+#else |
475 |
+ | O_NDELAY |
476 |
+#endif |
477 |
+ , perm); |
478 |
+ |
479 |
+ if (fd < 0) return (fd); |
480 |
+ if (fcntl(fd, F_SETFL, (mode & O_APPEND)) || fstat(fd, &stat1) |
481 |
+ || lstat(path, &stat2)) |
482 |
+ { |
483 |
+ close(fd); |
484 |
+ return (-1); |
485 |
+ } |
486 |
+ |
487 |
+ if (stat1.st_dev != stat2.st_dev || stat1.st_ino != stat2.st_ino) |
488 |
+ { |
489 |
+ close(fd); |
490 |
+ errno=ENOENT; |
491 |
+ return (-1); |
492 |
+ } |
493 |
+ |
494 |
+ return (fd); |
495 |
+} |
496 |
diff -ruN maildirparsequota.c maildirparsequota.c |
497 |
--- maildirparsequota.c Thu Jan 1 01:00:00 1970 |
498 |
+++ maildirparsequota.c Wed Aug 6 17:09:48 2003 |
499 |
@@ -0,0 +1,44 @@ |
500 |
+/* |
501 |
+** Copyright 1998 - 1999 Double Precision, Inc. |
502 |
+** See COPYING for distribution information. |
503 |
+*/ |
504 |
+ |
505 |
+#if HAVE_CONFIG_H |
506 |
+#include "config.h" |
507 |
+#endif |
508 |
+#include "maildirquota.h" |
509 |
+#include <stdlib.h> |
510 |
+#include <string.h> |
511 |
+ |
512 |
+static const char rcsid[]="$Id: maildirparsequota.c,v 1.2 1999/12/06 13:21:05 mrsam Exp $"; |
513 |
+ |
514 |
+int maildir_parsequota(const char *n, unsigned long *s) |
515 |
+{ |
516 |
+const char *o; |
517 |
+int yes; |
518 |
+ |
519 |
+ if ((o=strrchr(n, '/')) == 0) o=n; |
520 |
+ |
521 |
+ for (; *o; o++) |
522 |
+ if (*o == ':') break; |
523 |
+ yes=0; |
524 |
+ for ( ; o >= n; --o) |
525 |
+ { |
526 |
+ if (*o == '/') break; |
527 |
+ |
528 |
+ if (*o == ',' && o[1] == 'S' && o[2] == '=') |
529 |
+ { |
530 |
+ yes=1; |
531 |
+ o += 3; |
532 |
+ break; |
533 |
+ } |
534 |
+ } |
535 |
+ if (yes) |
536 |
+ { |
537 |
+ *s=0; |
538 |
+ while (*o >= '0' && *o <= '9') |
539 |
+ *s= *s*10 + (*o++ - '0'); |
540 |
+ return (0); |
541 |
+ } |
542 |
+ return (-1); |
543 |
+} |
544 |
diff -ruN maildirquota.c maildirquota.c |
545 |
--- maildirquota.c Thu Jan 1 01:00:00 1970 |
546 |
+++ maildirquota.c Wed Aug 6 17:09:48 2003 |
547 |
@@ -0,0 +1,685 @@ |
548 |
+/* |
549 |
+** Copyright 1998 - 2002 Double Precision, Inc. |
550 |
+** See COPYING for distribution information. |
551 |
+*/ |
552 |
+ |
553 |
+#if HAVE_CONFIG_H |
554 |
+#include "config.h" |
555 |
+#endif |
556 |
+ |
557 |
+#include <sys/types.h> |
558 |
+/* #if HAVE_DIRENT_H */ |
559 |
+#include <dirent.h> |
560 |
+#define NAMLEN(dirent) strlen((dirent)->d_name) |
561 |
+/* #else |
562 |
+#define dirent direct |
563 |
+#define NAMLEN(dirent) (dirent)->d_namlen |
564 |
+#if HAVE_SYS_NDIR_H |
565 |
+#include <sys/ndir.h> |
566 |
+#endif |
567 |
+#if HAVE_SYS_DIR_H |
568 |
+#include <sys/dir.h> |
569 |
+#endif |
570 |
+#if HAVE_NDIR_H |
571 |
+#include <ndir.h> |
572 |
+#endif |
573 |
+#endif */ |
574 |
+#include <sys/types.h> |
575 |
+/* #if HAVE_SYS_STAT_H */ |
576 |
+#include <sys/stat.h> |
577 |
+/* #endif */ |
578 |
+#include <sys/uio.h> |
579 |
+ |
580 |
+#include "maildirquota.h" |
581 |
+#include "maildirmisc.h" |
582 |
+#include <stdio.h> |
583 |
+#include <stdlib.h> |
584 |
+#include <string.h> |
585 |
+#include <errno.h> |
586 |
+/* #if HAVE_FCNTL_H */ |
587 |
+#include <fcntl.h> |
588 |
+/* #endif */ |
589 |
+#if HAVE_UNISTD_H |
590 |
+#include <unistd.h> |
591 |
+#endif |
592 |
+#include <time.h> |
593 |
+#include "numlib.h" |
594 |
+ |
595 |
+static const char rcsid[]="$Id: maildirquota.c,v 1.9 2002/05/01 04:05:33 mrsam Exp $"; |
596 |
+ |
597 |
+/* Read the maildirsize file */ |
598 |
+ |
599 |
+int maildirsize_read(const char *filename, /* The filename */ |
600 |
+ int *fdptr, /* Keep the file descriptor open */ |
601 |
+ off_t *sizeptr, /* Grand total of maildir size */ |
602 |
+ unsigned *cntptr, /* Grand total of message count */ |
603 |
+ unsigned *nlines, /* # of lines in maildirsize */ |
604 |
+ struct stat *statptr) /* The stats on maildirsize */ |
605 |
+{ |
606 |
+char buf[5120]; |
607 |
+int f; |
608 |
+char *p; |
609 |
+unsigned l; |
610 |
+int n; |
611 |
+int first; |
612 |
+ |
613 |
+ if ((f=maildir_safeopen(filename, O_RDWR|O_APPEND, 0)) < 0) |
614 |
+ return (-1); |
615 |
+ p=buf; |
616 |
+ l=sizeof(buf); |
617 |
+ |
618 |
+ while (l) |
619 |
+ { |
620 |
+ n=read(f, p, l); |
621 |
+ if (n < 0) |
622 |
+ { |
623 |
+ close(f); |
624 |
+ return (-1); |
625 |
+ } |
626 |
+ if (n == 0) break; |
627 |
+ p += n; |
628 |
+ l -= n; |
629 |
+ } |
630 |
+ if (l == 0 || fstat(f, statptr)) /* maildir too big */ |
631 |
+ { |
632 |
+ close(f); |
633 |
+ return (-1); |
634 |
+ } |
635 |
+ |
636 |
+ *sizeptr=0; |
637 |
+ *cntptr=0; |
638 |
+ *nlines=0; |
639 |
+ *p=0; |
640 |
+ p=buf; |
641 |
+ first=1; |
642 |
+ while (*p) |
643 |
+ { |
644 |
+ long n=0; |
645 |
+ int c=0; |
646 |
+ char *q=p; |
647 |
+ |
648 |
+ while (*p) |
649 |
+ if (*p++ == '\n') |
650 |
+ { |
651 |
+ p[-1]=0; |
652 |
+ break; |
653 |
+ } |
654 |
+ |
655 |
+ if (first) |
656 |
+ { |
657 |
+ first=0; |
658 |
+ continue; |
659 |
+ } |
660 |
+ sscanf(q, "%ld %d", &n, &c); |
661 |
+ *sizeptr += n; |
662 |
+ *cntptr += c; |
663 |
+ ++ *nlines; |
664 |
+ } |
665 |
+ *fdptr=f; |
666 |
+ return (0); |
667 |
+} |
668 |
+ |
669 |
+static char *makenewmaildirsizename(const char *, int *); |
670 |
+static int countcurnew(const char *, time_t *, off_t *, unsigned *); |
671 |
+static int countsubdir(const char *, const char *, |
672 |
+ time_t *, off_t *, unsigned *); |
673 |
+static int statcurnew(const char *, time_t *); |
674 |
+static int statsubdir(const char *, const char *, time_t *); |
675 |
+ |
676 |
+#define MDQUOTA_SIZE 'S' /* Total size of all messages in maildir */ |
677 |
+#define MDQUOTA_BLOCKS 'B' /* Total # of blocks for all messages in |
678 |
+ maildir -- NOT IMPLEMENTED */ |
679 |
+#define MDQUOTA_COUNT 'C' /* Total number of messages in maildir */ |
680 |
+ |
681 |
+static int qcalc(off_t s, unsigned n, const char *quota, int *percentage) |
682 |
+{ |
683 |
+off_t i; |
684 |
+int spercentage=0; |
685 |
+int npercentage=0; |
686 |
+ |
687 |
+ errno=ENOSPC; |
688 |
+ while (quota && *quota) |
689 |
+ { |
690 |
+ int x=1; |
691 |
+ |
692 |
+ if (*quota < '0' || *quota > '9') |
693 |
+ { |
694 |
+ ++quota; |
695 |
+ continue; |
696 |
+ } |
697 |
+ i=0; |
698 |
+ while (*quota >= '0' && *quota <= '9') |
699 |
+ i=i*10 + (*quota++ - '0'); |
700 |
+ switch (*quota) { |
701 |
+ default: |
702 |
+ if (i < s) |
703 |
+ { |
704 |
+ *percentage=100; |
705 |
+ return (-1); |
706 |
+ } |
707 |
+ |
708 |
+ /* |
709 |
+ ** For huge quotas, over 20mb, |
710 |
+ ** divide numerator & denominator by 1024 to prevent |
711 |
+ ** an overflow when multiplying by 100 |
712 |
+ */ |
713 |
+ |
714 |
+ x=1; |
715 |
+ if (i > 20000000) x=1024; |
716 |
+ |
717 |
+ spercentage = i ? (s/x) * 100 / (i/x):100; |
718 |
+ break; |
719 |
+ case 'C': |
720 |
+ |
721 |
+ if (i < n) |
722 |
+ { |
723 |
+ *percentage=100; |
724 |
+ return (-1); |
725 |
+ } |
726 |
+ |
727 |
+ /* Ditto */ |
728 |
+ |
729 |
+ x=1; |
730 |
+ if (i > 20000000) x=1024; |
731 |
+ |
732 |
+ npercentage = i ? ((off_t)n/x) * 100 / (i/x):100; |
733 |
+ break; |
734 |
+ } |
735 |
+ } |
736 |
+ *percentage = spercentage > npercentage ? spercentage:npercentage; |
737 |
+ return (0); |
738 |
+} |
739 |
+ |
740 |
+static int doaddquota(const char *, int, const char *, long, int, int); |
741 |
+ |
742 |
+static int docheckquota(const char *dir, |
743 |
+ int *maildirsize_fdptr, |
744 |
+ const char *quota_type, |
745 |
+ long xtra_size, |
746 |
+ int xtra_cnt, int *percentage); |
747 |
+ |
748 |
+ |
749 |
+int maildir_checkquota(const char *dir, |
750 |
+ int *maildirsize_fdptr, |
751 |
+ const char *quota_type, |
752 |
+ long xtra_size, |
753 |
+ int xtra_cnt) |
754 |
+{ |
755 |
+int dummy; |
756 |
+ |
757 |
+ return (docheckquota(dir, maildirsize_fdptr, quota_type, |
758 |
+ xtra_size, xtra_cnt, &dummy)); |
759 |
+} |
760 |
+ |
761 |
+int maildir_readquota(const char *dir, const char *quota_type) |
762 |
+{ |
763 |
+int percentage=0; |
764 |
+int fd=-1; |
765 |
+ |
766 |
+ (void)docheckquota(dir, &fd, quota_type, 0, 0, &percentage); |
767 |
+ if (fd >= 0) |
768 |
+ close(fd); |
769 |
+ return (percentage); |
770 |
+} |
771 |
+ |
772 |
+static int docheckquota(const char *dir, |
773 |
+ int *maildirsize_fdptr, |
774 |
+ const char *quota_type, |
775 |
+ long xtra_size, |
776 |
+ int xtra_cnt, |
777 |
+ int *percentage) |
778 |
+{ |
779 |
+char *checkfolder=(char *)malloc(strlen(dir)+sizeof("/maildirfolder")); |
780 |
+char *newmaildirsizename; |
781 |
+struct stat stat_buf; |
782 |
+int maildirsize_fd; |
783 |
+off_t maildirsize_size; |
784 |
+unsigned maildirsize_cnt; |
785 |
+unsigned maildirsize_nlines; |
786 |
+int n; |
787 |
+time_t tm; |
788 |
+time_t maxtime; |
789 |
+DIR *dirp; |
790 |
+struct dirent *de; |
791 |
+ |
792 |
+ if (checkfolder == 0) return (-1); |
793 |
+ *maildirsize_fdptr= -1; |
794 |
+ strcat(strcpy(checkfolder, dir), "/maildirfolder"); |
795 |
+ if (stat(checkfolder, &stat_buf) == 0) /* Go to parent */ |
796 |
+ { |
797 |
+ strcat(strcpy(checkfolder, dir), "/.."); |
798 |
+ n=docheckquota(checkfolder, maildirsize_fdptr, |
799 |
+ quota_type, xtra_size, xtra_cnt, percentage); |
800 |
+ free(checkfolder); |
801 |
+ return (n); |
802 |
+ } |
803 |
+ if (!quota_type || !*quota_type) return (0); |
804 |
+ |
805 |
+ strcat(strcpy(checkfolder, dir), "/maildirsize"); |
806 |
+ time(&tm); |
807 |
+ if (maildirsize_read(checkfolder, &maildirsize_fd, |
808 |
+ &maildirsize_size, &maildirsize_cnt, |
809 |
+ &maildirsize_nlines, &stat_buf) == 0) |
810 |
+ { |
811 |
+ n=qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt, |
812 |
+ quota_type, percentage); |
813 |
+ |
814 |
+ if (n == 0) |
815 |
+ { |
816 |
+ free(checkfolder); |
817 |
+ *maildirsize_fdptr=maildirsize_fd; |
818 |
+ return (0); |
819 |
+ } |
820 |
+ close(maildirsize_fd); |
821 |
+ |
822 |
+ if (maildirsize_nlines == 1 && tm < stat_buf.st_mtime + 15*60) |
823 |
+ return (n); |
824 |
+ } |
825 |
+ |
826 |
+ maxtime=0; |
827 |
+ maildirsize_size=0; |
828 |
+ maildirsize_cnt=0; |
829 |
+ |
830 |
+ if (countcurnew(dir, &maxtime, &maildirsize_size, &maildirsize_cnt)) |
831 |
+ { |
832 |
+ free(checkfolder); |
833 |
+ return (-1); |
834 |
+ } |
835 |
+ |
836 |
+ dirp=opendir(dir); |
837 |
+ while (dirp && (de=readdir(dirp)) != 0) |
838 |
+ { |
839 |
+ if (countsubdir(dir, de->d_name, &maxtime, &maildirsize_size, |
840 |
+ &maildirsize_cnt)) |
841 |
+ { |
842 |
+ free(checkfolder); |
843 |
+ closedir(dirp); |
844 |
+ return (-1); |
845 |
+ } |
846 |
+ } |
847 |
+ if (dirp) |
848 |
+ { |
849 |
+#if CLOSEDIR_VOID |
850 |
+ closedir(dirp); |
851 |
+#else |
852 |
+ if (closedir(dirp)) |
853 |
+ { |
854 |
+ free(checkfolder); |
855 |
+ return (-1); |
856 |
+ } |
857 |
+#endif |
858 |
+ } |
859 |
+ |
860 |
+ newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd); |
861 |
+ if (!newmaildirsizename) |
862 |
+ { |
863 |
+ free(checkfolder); |
864 |
+ return (-1); |
865 |
+ } |
866 |
+ |
867 |
+ *maildirsize_fdptr=maildirsize_fd; |
868 |
+ |
869 |
+ if (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size, |
870 |
+ maildirsize_cnt, 1)) |
871 |
+ { |
872 |
+ free(newmaildirsizename); |
873 |
+ unlink(newmaildirsizename); |
874 |
+ close(maildirsize_fd); |
875 |
+ *maildirsize_fdptr= -1; |
876 |
+ free(checkfolder); |
877 |
+ return (-1); |
878 |
+ } |
879 |
+ |
880 |
+ strcat(strcpy(checkfolder, dir), "/maildirsize"); |
881 |
+ |
882 |
+ if (rename(newmaildirsizename, checkfolder)) |
883 |
+ { |
884 |
+ free(checkfolder); |
885 |
+ unlink(newmaildirsizename); |
886 |
+ close(maildirsize_fd); |
887 |
+ *maildirsize_fdptr= -1; |
888 |
+ } |
889 |
+ free(checkfolder); |
890 |
+ free(newmaildirsizename); |
891 |
+ |
892 |
+ tm=0; |
893 |
+ |
894 |
+ if (statcurnew(dir, &tm)) |
895 |
+ { |
896 |
+ close(maildirsize_fd); |
897 |
+ *maildirsize_fdptr= -1; |
898 |
+ return (-1); |
899 |
+ } |
900 |
+ |
901 |
+ dirp=opendir(dir); |
902 |
+ while (dirp && (de=readdir(dirp)) != 0) |
903 |
+ { |
904 |
+ if (statsubdir(dir, de->d_name, &tm)) |
905 |
+ { |
906 |
+ close(maildirsize_fd); |
907 |
+ *maildirsize_fdptr= -1; |
908 |
+ closedir(dirp); |
909 |
+ return (-1); |
910 |
+ } |
911 |
+ } |
912 |
+ if (dirp) |
913 |
+ { |
914 |
+#if CLOSEDIR_VOID |
915 |
+ closedir(dirp); |
916 |
+#else |
917 |
+ if (closedir(dirp)) |
918 |
+ { |
919 |
+ close(maildirsize_fd); |
920 |
+ *maildirsize_fdptr= -1; |
921 |
+ return (-1); |
922 |
+ } |
923 |
+#endif |
924 |
+ } |
925 |
+ |
926 |
+ if (tm != maxtime) /* Race condition, someone changed something */ |
927 |
+ { |
928 |
+ errno=EAGAIN; |
929 |
+ return (-1); |
930 |
+ } |
931 |
+ |
932 |
+ return (qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt, |
933 |
+ quota_type, percentage)); |
934 |
+} |
935 |
+ |
936 |
+int maildir_addquota(const char *dir, int maildirsize_fd, |
937 |
+ const char *quota_type, long maildirsize_size, int maildirsize_cnt) |
938 |
+{ |
939 |
+ if (!quota_type || !*quota_type) return (0); |
940 |
+ return (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size, |
941 |
+ maildirsize_cnt, 0)); |
942 |
+} |
943 |
+ |
944 |
+static int doaddquota(const char *dir, int maildirsize_fd, |
945 |
+ const char *quota_type, long maildirsize_size, int maildirsize_cnt, |
946 |
+ int isnew) |
947 |
+{ |
948 |
+union { |
949 |
+ char buf[100]; |
950 |
+ struct stat stat_buf; |
951 |
+ } u; /* Scrooge */ |
952 |
+char *newname2=0; |
953 |
+char *newmaildirsizename=0; |
954 |
+struct iovec iov[3]; |
955 |
+int niov; |
956 |
+struct iovec *p; |
957 |
+int n; |
958 |
+ |
959 |
+ niov=0; |
960 |
+ if ( maildirsize_fd < 0) |
961 |
+ { |
962 |
+ newname2=(char *)malloc(strlen(dir)+sizeof("/maildirfolder")); |
963 |
+ if (!newname2) return (-1); |
964 |
+ strcat(strcpy(newname2, dir), "/maildirfolder"); |
965 |
+ if (stat(newname2, &u.stat_buf) == 0) |
966 |
+ { |
967 |
+ strcat(strcpy(newname2, dir), "/.."); |
968 |
+ n=doaddquota(newname2, maildirsize_fd, quota_type, |
969 |
+ maildirsize_size, maildirsize_cnt, |
970 |
+ isnew); |
971 |
+ free(newname2); |
972 |
+ return (n); |
973 |
+ } |
974 |
+ |
975 |
+ strcat(strcpy(newname2, dir), "/maildirsize"); |
976 |
+ |
977 |
+ if ((maildirsize_fd=maildir_safeopen(newname2, |
978 |
+ O_RDWR|O_APPEND, 0644)) < 0) |
979 |
+ { |
980 |
+ newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd); |
981 |
+ if (!newmaildirsizename) |
982 |
+ { |
983 |
+ free(newname2); |
984 |
+ return (-1); |
985 |
+ } |
986 |
+ |
987 |
+ maildirsize_fd=maildir_safeopen(newmaildirsizename, |
988 |
+ O_CREAT|O_RDWR|O_APPEND, 0644); |
989 |
+ |
990 |
+ if (maildirsize_fd < 0) |
991 |
+ { |
992 |
+ free(newname2); |
993 |
+ return (-1); |
994 |
+ } |
995 |
+ isnew=1; |
996 |
+ } |
997 |
+ } |
998 |
+ |
999 |
+ if (isnew) |
1000 |
+ { |
1001 |
+ iov[0].iov_base=(caddr_t)quota_type; |
1002 |
+ iov[0].iov_len=strlen(quota_type); |
1003 |
+ iov[1].iov_base=(caddr_t)"\n"; |
1004 |
+ iov[1].iov_len=1; |
1005 |
+ niov=2; |
1006 |
+ } |
1007 |
+ |
1008 |
+ |
1009 |
+ sprintf(u.buf, "%ld %d\n", maildirsize_size, maildirsize_cnt); |
1010 |
+ iov[niov].iov_base=(caddr_t)u.buf; |
1011 |
+ iov[niov].iov_len=strlen(u.buf); |
1012 |
+ |
1013 |
+ p=iov; |
1014 |
+ ++niov; |
1015 |
+ n=0; |
1016 |
+ while (niov) |
1017 |
+ { |
1018 |
+ if (n) |
1019 |
+ { |
1020 |
+ if (n < p->iov_len) |
1021 |
+ { |
1022 |
+ p->iov_base= |
1023 |
+ (caddr_t)((char *)p->iov_base + n); |
1024 |
+ p->iov_len -= n; |
1025 |
+ } |
1026 |
+ else |
1027 |
+ { |
1028 |
+ n -= p->iov_len; |
1029 |
+ ++p; |
1030 |
+ --niov; |
1031 |
+ continue; |
1032 |
+ } |
1033 |
+ } |
1034 |
+ |
1035 |
+ n=writev( maildirsize_fd, p, niov); |
1036 |
+ |
1037 |
+ if (n <= 0) |
1038 |
+ { |
1039 |
+ if (newname2) |
1040 |
+ { |
1041 |
+ close(maildirsize_fd); |
1042 |
+ free(newname2); |
1043 |
+ } |
1044 |
+ return (-1); |
1045 |
+ } |
1046 |
+ } |
1047 |
+ if (newname2) |
1048 |
+ { |
1049 |
+ close(maildirsize_fd); |
1050 |
+ |
1051 |
+ if (newmaildirsizename) |
1052 |
+ { |
1053 |
+ rename(newmaildirsizename, newname2); |
1054 |
+ free(newmaildirsizename); |
1055 |
+ } |
1056 |
+ free(newname2); |
1057 |
+ } |
1058 |
+ return (0); |
1059 |
+} |
1060 |
+ |
1061 |
+/* New maildirsize is built in the tmp subdirectory */ |
1062 |
+ |
1063 |
+static char *makenewmaildirsizename(const char *dir, int *fd) |
1064 |
+{ |
1065 |
+char hostname[256]; |
1066 |
+struct stat stat_buf; |
1067 |
+time_t t; |
1068 |
+char *p; |
1069 |
+ |
1070 |
+ hostname[0]=0; |
1071 |
+ hostname[sizeof(hostname)-1]=0; |
1072 |
+ gethostname(hostname, sizeof(hostname)-1); |
1073 |
+ p=(char *)malloc(strlen(dir)+strlen(hostname)+130); |
1074 |
+ if (!p) return (0); |
1075 |
+ |
1076 |
+ for (;;) |
1077 |
+ { |
1078 |
+ char tbuf[NUMBUFSIZE]; |
1079 |
+ char pbuf[NUMBUFSIZE]; |
1080 |
+ |
1081 |
+ time(&t); |
1082 |
+ strcat(strcpy(p, dir), "/tmp/"); |
1083 |
+ sprintf(p+strlen(p), "%s.%s_NeWmAiLdIrSiZe.%s", |
1084 |
+ str_time_t(t, tbuf), |
1085 |
+ str_pid_t(getpid(), pbuf), hostname); |
1086 |
+ |
1087 |
+ if (stat( (const char *)p, &stat_buf) < 0 && |
1088 |
+ (*fd=maildir_safeopen(p, |
1089 |
+ O_CREAT|O_RDWR|O_APPEND, 0644)) >= 0) |
1090 |
+ break; |
1091 |
+ sleep(3); |
1092 |
+ } |
1093 |
+ return (p); |
1094 |
+} |
1095 |
+ |
1096 |
+static int statcurnew(const char *dir, time_t *maxtimestamp) |
1097 |
+{ |
1098 |
+char *p=(char *)malloc(strlen(dir)+5); |
1099 |
+struct stat stat_buf; |
1100 |
+ |
1101 |
+ if (!p) return (-1); |
1102 |
+ strcat(strcpy(p, dir), "/cur"); |
1103 |
+ if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp) |
1104 |
+ *maxtimestamp=stat_buf.st_mtime; |
1105 |
+ strcat(strcpy(p, dir), "/new"); |
1106 |
+ if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp) |
1107 |
+ *maxtimestamp=stat_buf.st_mtime; |
1108 |
+ free(p); |
1109 |
+ return (0); |
1110 |
+} |
1111 |
+ |
1112 |
+static int statsubdir(const char *dir, const char *subdir, time_t *maxtime) |
1113 |
+{ |
1114 |
+char *p; |
1115 |
+int n; |
1116 |
+ |
1117 |
+ if ( *subdir != '.' || strcmp(subdir, ".") == 0 || |
1118 |
+ strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0) |
1119 |
+ return (0); |
1120 |
+ |
1121 |
+ p=(char *)malloc(strlen(dir)+strlen(subdir)+2); |
1122 |
+ if (!p) return (-1); |
1123 |
+ strcat(strcat(strcpy(p, dir), "/"), subdir); |
1124 |
+ n=statcurnew(p, maxtime); |
1125 |
+ free(p); |
1126 |
+ return (n); |
1127 |
+} |
1128 |
+ |
1129 |
+static int docount(const char *, time_t *, off_t *, unsigned *); |
1130 |
+ |
1131 |
+static int countcurnew(const char *dir, time_t *maxtime, |
1132 |
+ off_t *sizep, unsigned *cntp) |
1133 |
+{ |
1134 |
+char *p=(char *)malloc(strlen(dir)+5); |
1135 |
+int n; |
1136 |
+ |
1137 |
+ if (!p) return (-1); |
1138 |
+ strcat(strcpy(p, dir), "/new"); |
1139 |
+ n=docount(p, maxtime, sizep, cntp); |
1140 |
+ if (n == 0) |
1141 |
+ { |
1142 |
+ strcat(strcpy(p, dir), "/cur"); |
1143 |
+ n=docount(p, maxtime, sizep, cntp); |
1144 |
+ } |
1145 |
+ free(p); |
1146 |
+ return (n); |
1147 |
+} |
1148 |
+ |
1149 |
+static int countsubdir(const char *dir, const char *subdir, time_t *maxtime, |
1150 |
+ off_t *sizep, unsigned *cntp) |
1151 |
+{ |
1152 |
+char *p; |
1153 |
+int n; |
1154 |
+ |
1155 |
+ if ( *subdir != '.' || strcmp(subdir, ".") == 0 || |
1156 |
+ strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0) |
1157 |
+ return (0); |
1158 |
+ |
1159 |
+ p=(char *)malloc(strlen(dir)+strlen(subdir)+2); |
1160 |
+ if (!p) return (2); |
1161 |
+ strcat(strcat(strcpy(p, dir), "/"), subdir); |
1162 |
+ n=countcurnew(p, maxtime, sizep, cntp); |
1163 |
+ free(p); |
1164 |
+ return (n); |
1165 |
+} |
1166 |
+ |
1167 |
+static int docount(const char *dir, time_t *dirstamp, |
1168 |
+ off_t *sizep, unsigned *cntp) |
1169 |
+{ |
1170 |
+struct stat stat_buf; |
1171 |
+char *p; |
1172 |
+DIR *dirp; |
1173 |
+struct dirent *de; |
1174 |
+unsigned long s; |
1175 |
+ |
1176 |
+ if (stat(dir, &stat_buf)) return (0); /* Ignore */ |
1177 |
+ if (stat_buf.st_mtime > *dirstamp) *dirstamp=stat_buf.st_mtime; |
1178 |
+ if ((dirp=opendir(dir)) == 0) return (0); |
1179 |
+ while ((de=readdir(dirp)) != 0) |
1180 |
+ { |
1181 |
+ const char *n=de->d_name; |
1182 |
+ |
1183 |
+ if (*n == '.') continue; |
1184 |
+ |
1185 |
+ /* PATCH - do not count msgs marked as deleted */ |
1186 |
+ |
1187 |
+ for ( ; *n; n++) |
1188 |
+ { |
1189 |
+ if (n[0] != ':' || n[1] != '2' || |
1190 |
+ n[2] != ',') continue; |
1191 |
+ n += 3; |
1192 |
+ while (*n >= 'A' && *n <= 'Z') |
1193 |
+ { |
1194 |
+ if (*n == 'T') break; |
1195 |
+ ++n; |
1196 |
+ } |
1197 |
+ break; |
1198 |
+ } |
1199 |
+ if (*n == 'T') continue; |
1200 |
+ n=de->d_name; |
1201 |
+ |
1202 |
+ |
1203 |
+ if (maildir_parsequota(n, &s) == 0) |
1204 |
+ stat_buf.st_size=s; |
1205 |
+ else |
1206 |
+ { |
1207 |
+ p=(char *)malloc(strlen(dir)+strlen(n)+2); |
1208 |
+ if (!p) |
1209 |
+ { |
1210 |
+ closedir(dirp); |
1211 |
+ return (-1); |
1212 |
+ } |
1213 |
+ strcat(strcat(strcpy(p, dir), "/"), n); |
1214 |
+ if (stat(p, &stat_buf)) |
1215 |
+ { |
1216 |
+ free(p); |
1217 |
+ continue; |
1218 |
+ } |
1219 |
+ free(p); |
1220 |
+ } |
1221 |
+ *sizep += stat_buf.st_size; |
1222 |
+ ++*cntp; |
1223 |
+ } |
1224 |
+ |
1225 |
+#if CLOSEDIR_VOID |
1226 |
+ closedir(dirp); |
1227 |
+#else |
1228 |
+ if (closedir(dirp)) |
1229 |
+ return (-1); |
1230 |
+#endif |
1231 |
+ return (0); |
1232 |
+} |
1233 |
diff -ruN maildirquota.h maildirquota.h |
1234 |
--- maildirquota.h Thu Jan 1 01:00:00 1970 |
1235 |
+++ maildirquota.h Wed Aug 6 17:09:48 2003 |
1236 |
@@ -0,0 +1,45 @@ |
1237 |
+#ifndef maildirquota_h |
1238 |
+#define maildirquota_h |
1239 |
+ |
1240 |
+/* |
1241 |
+** Copyright 1998 - 1999 Double Precision, Inc. |
1242 |
+** See COPYING for distribution information. |
1243 |
+*/ |
1244 |
+ |
1245 |
+#if HAVE_CONFIG_H |
1246 |
+#include "config.h" |
1247 |
+#endif |
1248 |
+ |
1249 |
+#include <sys/types.h> |
1250 |
+#include <stdio.h> |
1251 |
+ |
1252 |
+#ifdef __cplusplus |
1253 |
+extern "C" { |
1254 |
+#endif |
1255 |
+ |
1256 |
+static const char maildirquota_h_rcsid[]="$Id: maildirquota.h,v 1.2 2000/09/04 17:10:28 mrsam Exp $"; |
1257 |
+ |
1258 |
+int maildir_checkquota(const char *, /* Pointer to directory */ |
1259 |
+ int *, /* Initialized to -1, or opened descriptor for maildirsize */ |
1260 |
+ const char *, /* The quota */ |
1261 |
+ long, /* Extra bytes planning to add/remove from maildir */ |
1262 |
+ int); /* Extra messages planning to add/remove from maildir */ |
1263 |
+ |
1264 |
+int maildir_addquota(const char *, /* Pointer to the maildir */ |
1265 |
+ int, /* Must be the int pointed to by 2nd arg to checkquota */ |
1266 |
+ const char *, /* The quota */ |
1267 |
+ long, /* +/- bytes */ |
1268 |
+ int); /* +/- files */ |
1269 |
+ |
1270 |
+int maildir_readquota(const char *, /* Directory */ |
1271 |
+ const char *); /* Quota, from getquota */ |
1272 |
+ |
1273 |
+int maildir_parsequota(const char *, unsigned long *); |
1274 |
+ /* Attempt to parse file size encoded in filename. Returns 0 if |
1275 |
+ ** parsed, non-zero if we didn't parse. */ |
1276 |
+ |
1277 |
+#ifdef __cplusplus |
1278 |
+} |
1279 |
+#endif |
1280 |
+ |
1281 |
+#endif |
1282 |
diff -ruN numlib.h numlib.h |
1283 |
--- numlib.h Thu Jan 1 01:00:00 1970 |
1284 |
+++ numlib.h Wed Aug 6 17:09:48 2003 |
1285 |
@@ -0,0 +1,45 @@ |
1286 |
+#ifndef numlib_h |
1287 |
+#define numlib_h |
1288 |
+ |
1289 |
+/* |
1290 |
+** Copyright 1998 - 1999 Double Precision, Inc. |
1291 |
+** See COPYING for distribution information. |
1292 |
+*/ |
1293 |
+ |
1294 |
+#ifdef __cplusplus |
1295 |
+extern "C" { |
1296 |
+#endif |
1297 |
+ |
1298 |
+static const char numlib_h_rcsid[]="$Id: numlib.h,v 1.3 2001/08/12 15:46:40 mrsam Exp $"; |
1299 |
+ |
1300 |
+#if HAVE_CONFIG_H |
1301 |
+#include "config.h" |
1302 |
+#endif |
1303 |
+ |
1304 |
+#include <sys/types.h> |
1305 |
+#include <time.h> |
1306 |
+ |
1307 |
+#define NUMBUFSIZE 60 |
1308 |
+ |
1309 |
+/* Convert various system types to decimal */ |
1310 |
+ |
1311 |
+char *str_time_t(time_t, char *); |
1312 |
+char *str_off_t(off_t, char *); |
1313 |
+char *str_pid_t(pid_t, char *); |
1314 |
+char *str_ino_t(ino_t, char *); |
1315 |
+char *str_uid_t(uid_t, char *); |
1316 |
+char *str_gid_t(gid_t, char *); |
1317 |
+char *str_size_t(size_t, char *); |
1318 |
+ |
1319 |
+char *str_sizekb(unsigned long, char *); /* X Kb or X Mb */ |
1320 |
+ |
1321 |
+/* Convert selected system types to hex */ |
1322 |
+ |
1323 |
+char *strh_time_t(time_t, char *); |
1324 |
+char *strh_pid_t(pid_t, char *); |
1325 |
+char *strh_ino_t(ino_t, char *); |
1326 |
+ |
1327 |
+#ifdef __cplusplus |
1328 |
+} |
1329 |
+#endif |
1330 |
+#endif |
1331 |
diff -ruN overmaildirquota.c overmaildirquota.c |
1332 |
--- overmaildirquota.c Thu Jan 1 01:00:00 1970 |
1333 |
+++ overmaildirquota.c Wed Aug 6 17:10:33 2003 |
1334 |
@@ -0,0 +1,42 @@ |
1335 |
+/* |
1336 |
+** Copyright 1998 - 1999 Double Precision, Inc. |
1337 |
+** See COPYING for distribution information. |
1338 |
+*/ |
1339 |
+ |
1340 |
+#if HAVE_CONFIG_H |
1341 |
+#include "config.h" |
1342 |
+#endif |
1343 |
+#include "maildirquota.h" |
1344 |
+#include <stdlib.h> |
1345 |
+#include <string.h> |
1346 |
+#include <errno.h> |
1347 |
+#include <sys/stat.h> |
1348 |
+ |
1349 |
+static const char rcsid[]="$Id: overquota.c,v 1.0 2002/06/09 16:21:05 mrsam Exp $"; |
1350 |
+ |
1351 |
+ |
1352 |
+int user_over_maildirquota( const char *dir, const char *q) |
1353 |
+{ |
1354 |
+struct stat stat_buf; |
1355 |
+int quotafd; |
1356 |
+int ret_value; |
1357 |
+ |
1358 |
+ if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) && |
1359 |
+ stat_buf.st_size > 0 && *q) |
1360 |
+ { |
1361 |
+ if (maildir_checkquota(dir, "afd, q, stat_buf.st_size, 1) |
1362 |
+ && errno != EAGAIN) |
1363 |
+ { |
1364 |
+ if (quotafd >= 0) close(quotafd); |
1365 |
+ ret_value = 1; |
1366 |
+ } else { |
1367 |
+ maildir_addquota(dir, quotafd, q, stat_buf.st_size, 1); |
1368 |
+ if (quotafd >= 0) close(quotafd); |
1369 |
+ ret_value = 0; |
1370 |
+ } |
1371 |
+ } else { |
1372 |
+ ret_value = 0; |
1373 |
+ } |
1374 |
+ |
1375 |
+ return(ret_value); |
1376 |
+} |
1377 |
diff -ruN qmail-local.c qmail-local.c |
1378 |
--- qmail-local.c Wed Aug 6 17:05:13 2003 |
1379 |
+++ qmail-local.c Wed Aug 6 17:09:48 2003 |
1380 |
@@ -66,6 +66,7 @@ |
1381 |
|
1382 |
char buf[1024]; |
1383 |
char outbuf[1024]; |
1384 |
+#define QUOTABUFSIZE 256 |
1385 |
|
1386 |
/* child process */ |
1387 |
|
1388 |
@@ -86,9 +87,15 @@ |
1389 |
int fd; |
1390 |
substdio ss; |
1391 |
substdio ssout; |
1392 |
+ char quotabuf[QUOTABUFSIZE]; |
1393 |
|
1394 |
sig_alarmcatch(sigalrm); |
1395 |
if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); } |
1396 |
+ if (maildir_getquota(dir, quotabuf) == 0) { |
1397 |
+ if (user_over_maildirquota(dir,quotabuf)==1) { |
1398 |
+ _exit(1); |
1399 |
+ } |
1400 |
+ } |
1401 |
pid = getpid(); |
1402 |
host[0] = 0; |
1403 |
gethostname(host,sizeof(host)); |
1404 |
@@ -99,7 +106,10 @@ |
1405 |
s += fmt_str(s,"tmp/"); |
1406 |
s += fmt_ulong(s,time); *s++ = '.'; |
1407 |
s += fmt_ulong(s,pid); *s++ = '.'; |
1408 |
- s += fmt_strn(s,host,sizeof(host)); *s++ = 0; |
1409 |
+ s += fmt_strn(s,host,sizeof(host)); |
1410 |
+ s += fmt_strn(s,",S=",sizeof(",S=")); |
1411 |
+ if (fstat(0,&st) == -1) if (errno == error_noent) break; |
1412 |
+ s += fmt_ulong(s,st.st_size+rpline.len+dtline.len); *s++ = 0; |
1413 |
if (stat(fntmptph,&st) == -1) if (errno == error_noent) break; |
1414 |
/* really should never get to this point */ |
1415 |
if (loop == 2) _exit(1); |
1416 |
@@ -159,6 +169,7 @@ |
1417 |
switch(wait_exitcode(wstat)) |
1418 |
{ |
1419 |
case 0: break; |
1420 |
+ case 1: strerr_die1x(1, "User over quota. (#5.1.1)"); |
1421 |
case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)"); |
1422 |
case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)"); |
1423 |
case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)"); |
1424 |
diff -ruN qmail-pop3d.c qmail-pop3d.c |
1425 |
--- qmail-pop3d.c Wed Aug 6 17:05:13 2003 |
1426 |
+++ qmail-pop3d.c Wed Aug 6 17:09:48 2003 |
1427 |
@@ -16,6 +16,11 @@ |
1428 |
#include "readwrite.h" |
1429 |
#include "timeoutread.h" |
1430 |
#include "timeoutwrite.h" |
1431 |
+#include <errno.h> |
1432 |
+#include "maildirquota.h" |
1433 |
+#include "maildirmisc.h" |
1434 |
+ |
1435 |
+#define QUOTABUFSIZE 256 |
1436 |
|
1437 |
void die() { _exit(0); } |
1438 |
|
1439 |
@@ -45,19 +50,15 @@ |
1440 |
{ |
1441 |
substdio_put(&ssout,buf,len); |
1442 |
} |
1443 |
-void puts(s) char *s; |
1444 |
-{ |
1445 |
- substdio_puts(&ssout,s); |
1446 |
-} |
1447 |
void flush() |
1448 |
{ |
1449 |
substdio_flush(&ssout); |
1450 |
} |
1451 |
void err(s) char *s; |
1452 |
{ |
1453 |
- puts("-ERR "); |
1454 |
- puts(s); |
1455 |
- puts("\r\n"); |
1456 |
+ substdio_puts(&ssout,"-ERR "); |
1457 |
+ substdio_puts(&ssout,s); |
1458 |
+ substdio_puts(&ssout,"\r\n"); |
1459 |
flush(); |
1460 |
} |
1461 |
|
1462 |
@@ -73,7 +74,7 @@ |
1463 |
void err_nosuch() { err("unable to open that message"); } |
1464 |
void err_nounlink() { err("unable to unlink all deleted messages"); } |
1465 |
|
1466 |
-void okay() { puts("+OK \r\n"); flush(); } |
1467 |
+void okay() { substdio_puts(&ssout,"+OK \r\n"); flush(); } |
1468 |
|
1469 |
void printfn(fn) char *fn; |
1470 |
{ |
1471 |
@@ -153,11 +154,11 @@ |
1472 |
|
1473 |
total = 0; |
1474 |
for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size; |
1475 |
- puts("+OK "); |
1476 |
+ substdio_puts(&ssout,"+OK "); |
1477 |
put(strnum,fmt_uint(strnum,numm)); |
1478 |
- puts(" "); |
1479 |
+ substdio_puts(&ssout," "); |
1480 |
put(strnum,fmt_ulong(strnum,total)); |
1481 |
- puts("\r\n"); |
1482 |
+ substdio_puts(&ssout,"\r\n"); |
1483 |
flush(); |
1484 |
} |
1485 |
|
1486 |
@@ -171,18 +172,41 @@ |
1487 |
|
1488 |
void pop3_last() |
1489 |
{ |
1490 |
- puts("+OK "); |
1491 |
+ substdio_puts(&ssout,"+OK "); |
1492 |
put(strnum,fmt_uint(strnum,last)); |
1493 |
- puts("\r\n"); |
1494 |
+ substdio_puts(&ssout,"\r\n"); |
1495 |
flush(); |
1496 |
} |
1497 |
|
1498 |
void pop3_quit() |
1499 |
{ |
1500 |
int i; |
1501 |
+ char quotabuf[QUOTABUFSIZE]; |
1502 |
+ int has_quota=maildir_getquota(".", quotabuf); |
1503 |
+ |
1504 |
+ long deleted_bytes=0; |
1505 |
+ long deleted_messages=0; |
1506 |
+ |
1507 |
for (i = 0;i < numm;++i) |
1508 |
if (m[i].flagdeleted) { |
1509 |
- if (unlink(m[i].fn) == -1) err_nounlink(); |
1510 |
+ unsigned long un=0; |
1511 |
+ const char *filename=m[i].fn; |
1512 |
+ if (has_quota == 0 && !MAILDIR_DELETED(filename)) { |
1513 |
+ if (maildir_parsequota(filename, &un)) { |
1514 |
+ struct stat stat_buf; |
1515 |
+ |
1516 |
+ if (stat(filename, &stat_buf) == 0) |
1517 |
+ un=stat_buf.st_size; |
1518 |
+ } |
1519 |
+ } |
1520 |
+ if (unlink(m[i].fn) == -1) { |
1521 |
+ err_nounlink(); |
1522 |
+ un=0; |
1523 |
+ } |
1524 |
+ if (un) { |
1525 |
+ deleted_bytes -= un; |
1526 |
+ deleted_messages -= 1; |
1527 |
+ } |
1528 |
} |
1529 |
else |
1530 |
if (str_start(m[i].fn,"new/")) { |
1531 |
@@ -192,6 +216,21 @@ |
1532 |
if (!stralloc_0(&line)) die_nomem(); |
1533 |
rename(m[i].fn,line.s); /* if it fails, bummer */ |
1534 |
} |
1535 |
+ |
1536 |
+ if (deleted_messages < 0) { |
1537 |
+ int quotafd; |
1538 |
+ |
1539 |
+ if (maildir_checkquota(".", "afd, quotabuf, deleted_bytes, |
1540 |
+ deleted_messages) && errno != EAGAIN && |
1541 |
+ deleted_bytes >= 0) |
1542 |
+ { |
1543 |
+ if (quotafd >= 0) close (quotafd); |
1544 |
+ } else { |
1545 |
+ maildir_addquota(".", quotafd, quotabuf, |
1546 |
+ deleted_bytes, deleted_messages); |
1547 |
+ if (quotafd >= 0) close(quotafd); |
1548 |
+ } |
1549 |
+ } |
1550 |
okay(); |
1551 |
die(); |
1552 |
} |
1553 |
@@ -222,10 +261,10 @@ |
1554 |
int flaguidl; |
1555 |
{ |
1556 |
put(strnum,fmt_uint(strnum,i + 1)); |
1557 |
- puts(" "); |
1558 |
+ substdio_puts(&ssout," "); |
1559 |
if (flaguidl) printfn(m[i].fn); |
1560 |
else put(strnum,fmt_ulong(strnum,m[i].size)); |
1561 |
- puts("\r\n"); |
1562 |
+ substdio_puts(&ssout,"\r\n"); |
1563 |
} |
1564 |
|
1565 |
void dolisting(arg,flaguidl) char *arg; int flaguidl; |
1566 |
@@ -234,7 +273,7 @@ |
1567 |
if (*arg) { |
1568 |
i = msgno(arg); |
1569 |
if (i == -1) return; |
1570 |
- puts("+OK "); |
1571 |
+ substdio_puts(&ssout,"+OK "); |
1572 |
list(i,flaguidl); |
1573 |
} |
1574 |
else { |
1575 |
@@ -242,7 +281,7 @@ |
1576 |
for (i = 0;i < numm;++i) |
1577 |
if (!m[i].flagdeleted) |
1578 |
list(i,flaguidl); |
1579 |
- puts(".\r\n"); |
1580 |
+ substdio_puts(&ssout,".\r\n"); |
1581 |
} |
1582 |
flush(); |
1583 |
} |
1584 |
diff -ruN strpidt.c strpidt.c |
1585 |
--- strpidt.c Thu Jan 1 01:00:00 1970 |
1586 |
+++ strpidt.c Wed Aug 6 17:09:48 2003 |
1587 |
@@ -0,0 +1,26 @@ |
1588 |
+/* |
1589 |
+** Copyright 1998 - 2000 Double Precision, Inc. |
1590 |
+** See COPYING for distribution information. |
1591 |
+*/ |
1592 |
+ |
1593 |
+#if HAVE_CONFIG_H |
1594 |
+#include "config.h" |
1595 |
+#endif |
1596 |
+#include "numlib.h" |
1597 |
+#include <string.h> |
1598 |
+ |
1599 |
+static const char rcsid[]="$Id: strpidt.c,v 1.3 2000/05/27 04:59:26 mrsam Exp $"; |
1600 |
+ |
1601 |
+char *str_pid_t(pid_t t, char *arg) |
1602 |
+{ |
1603 |
+char buf[NUMBUFSIZE]; |
1604 |
+char *p=buf+sizeof(buf)-1; |
1605 |
+ |
1606 |
+ *p=0; |
1607 |
+ do |
1608 |
+ { |
1609 |
+ *--p= '0' + (t % 10); |
1610 |
+ t=t / 10; |
1611 |
+ } while(t); |
1612 |
+ return (strcpy(arg, p)); |
1613 |
+} |
1614 |
diff -ruN strtimet.c strtimet.c |
1615 |
--- strtimet.c Thu Jan 1 01:00:00 1970 |
1616 |
+++ strtimet.c Wed Aug 6 17:09:48 2003 |
1617 |
@@ -0,0 +1,26 @@ |
1618 |
+/* |
1619 |
+** Copyright 1998 - 2000 Double Precision, Inc. |
1620 |
+** See COPYING for distribution information. |
1621 |
+*/ |
1622 |
+ |
1623 |
+#if HAVE_CONFIG_H |
1624 |
+#include "config.h" |
1625 |
+#endif |
1626 |
+#include "numlib.h" |
1627 |
+#include <string.h> |
1628 |
+ |
1629 |
+static const char rcsid[]="$Id: strtimet.c,v 1.3 2000/05/27 04:59:26 mrsam Exp $"; |
1630 |
+ |
1631 |
+char *str_time_t(time_t t, char *arg) |
1632 |
+{ |
1633 |
+char buf[NUMBUFSIZE]; |
1634 |
+char *p=buf+sizeof(buf)-1; |
1635 |
+ |
1636 |
+ *p=0; |
1637 |
+ do |
1638 |
+ { |
1639 |
+ *--p= '0' + (t % 10); |
1640 |
+ t=t / 10; |
1641 |
+ } while(t); |
1642 |
+ return (strcpy(arg, p)); |
1643 |
+} |