1 | |
---|
2 | /* |
---|
3 | * dropsbr.c -- create/read/manipulate mail drops |
---|
4 | * |
---|
5 | * $Id: dropsbr.c,v 1.2 2000-01-07 04:43:57 rbasch Exp $ |
---|
6 | */ |
---|
7 | |
---|
8 | #include <h/nmh.h> |
---|
9 | |
---|
10 | #ifndef MMDFONLY |
---|
11 | # include <h/mh.h> |
---|
12 | # include <h/dropsbr.h> |
---|
13 | # include <zotnet/mts/mts.h> |
---|
14 | # include <zotnet/tws/tws.h> |
---|
15 | #else |
---|
16 | # include "dropsbr.h" |
---|
17 | # include "strings.h" |
---|
18 | # include "mmdfonly.h" |
---|
19 | #endif |
---|
20 | |
---|
21 | #ifdef HAVE_ERRNO_H |
---|
22 | # include <errno.h> |
---|
23 | #endif |
---|
24 | |
---|
25 | #ifdef NTOHLSWAP |
---|
26 | # include <netinet/in.h> |
---|
27 | #else |
---|
28 | # undef ntohl |
---|
29 | # define ntohl(n) (n) |
---|
30 | #endif |
---|
31 | |
---|
32 | #include <fcntl.h> |
---|
33 | |
---|
34 | extern int errno; |
---|
35 | |
---|
36 | /* |
---|
37 | * static prototypes |
---|
38 | */ |
---|
39 | static int mbx_chk_mbox (int); |
---|
40 | static int mbx_chk_mmdf (int); |
---|
41 | static int map_open (char *, int *, int); |
---|
42 | |
---|
43 | |
---|
44 | /* |
---|
45 | * Main entry point to open/create and lock |
---|
46 | * a file or maildrop. |
---|
47 | */ |
---|
48 | |
---|
49 | int |
---|
50 | mbx_open (char *file, int mbx_style, uid_t uid, gid_t gid, mode_t mode) |
---|
51 | { |
---|
52 | int j, count, fd; |
---|
53 | struct stat st; |
---|
54 | |
---|
55 | j = 0; |
---|
56 | |
---|
57 | /* attempt to open and lock file */ |
---|
58 | for (count = 4; count > 0; count--) { |
---|
59 | if ((fd = lkopen (file, O_RDWR | O_CREAT | O_NONBLOCK, mode)) == NOTOK) { |
---|
60 | switch (errno) { |
---|
61 | #if defined(FCNTL_LOCKING) || defined(LOCKF_LOCKING) |
---|
62 | case EACCES: |
---|
63 | case EAGAIN: |
---|
64 | #endif |
---|
65 | |
---|
66 | #ifdef FLOCK_LOCKING |
---|
67 | case EWOULDBLOCK: |
---|
68 | #endif |
---|
69 | case ETXTBSY: |
---|
70 | j = errno; |
---|
71 | sleep (5); |
---|
72 | break; |
---|
73 | |
---|
74 | default: |
---|
75 | /* just return error */ |
---|
76 | return NOTOK; |
---|
77 | } |
---|
78 | } |
---|
79 | |
---|
80 | /* good file descriptor */ |
---|
81 | break; |
---|
82 | } |
---|
83 | |
---|
84 | errno = j; |
---|
85 | |
---|
86 | /* |
---|
87 | * Return if we still failed after 4 attempts, |
---|
88 | * or we just want to skip the sanity checks. |
---|
89 | */ |
---|
90 | if (fd == NOTOK || mbx_style == OTHER_FORMAT) |
---|
91 | return fd; |
---|
92 | |
---|
93 | /* |
---|
94 | * Do sanity checks on maildrop. |
---|
95 | */ |
---|
96 | if (fstat (fd, &st) == NOTOK) { |
---|
97 | /* |
---|
98 | * The stat failed. So we make sure file |
---|
99 | * has right ownership/modes |
---|
100 | */ |
---|
101 | chown (file, uid, gid); |
---|
102 | chmod (file, mode); |
---|
103 | } else if (st.st_size > (off_t) 0) { |
---|
104 | int status; |
---|
105 | |
---|
106 | /* check the maildrop */ |
---|
107 | switch (mbx_style) { |
---|
108 | case MMDF_FORMAT: |
---|
109 | default: |
---|
110 | status = mbx_chk_mmdf (fd); |
---|
111 | break; |
---|
112 | |
---|
113 | case MBOX_FORMAT: |
---|
114 | status = mbx_chk_mbox (fd); |
---|
115 | break; |
---|
116 | } |
---|
117 | |
---|
118 | /* if error, attempt to close it */ |
---|
119 | if (status == NOTOK) { |
---|
120 | close (fd); |
---|
121 | return NOTOK; |
---|
122 | } |
---|
123 | } |
---|
124 | |
---|
125 | return fd; |
---|
126 | } |
---|
127 | |
---|
128 | |
---|
129 | /* |
---|
130 | * Check/prepare MBOX style maildrop for appending. |
---|
131 | */ |
---|
132 | |
---|
133 | static int |
---|
134 | mbx_chk_mbox (int fd) |
---|
135 | { |
---|
136 | /* just seek to the end */ |
---|
137 | if (lseek (fd, (off_t) 0, SEEK_END) == (off_t) NOTOK) |
---|
138 | return NOTOK; |
---|
139 | |
---|
140 | return OK; |
---|
141 | } |
---|
142 | |
---|
143 | |
---|
144 | /* |
---|
145 | * Check/prepare MMDF style maildrop for appending. |
---|
146 | */ |
---|
147 | |
---|
148 | static int |
---|
149 | mbx_chk_mmdf (int fd) |
---|
150 | { |
---|
151 | size_t count; |
---|
152 | char ldelim[BUFSIZ]; |
---|
153 | |
---|
154 | count = strlen (mmdlm2); |
---|
155 | |
---|
156 | /* casting -count to off_t, seem to break FreeBSD 2.2.6 */ |
---|
157 | if (lseek (fd, (long) (-count), SEEK_END) == (off_t) NOTOK) |
---|
158 | return NOTOK; |
---|
159 | if (read (fd, ldelim, count) != count) |
---|
160 | return NOTOK; |
---|
161 | |
---|
162 | ldelim[count] = 0; |
---|
163 | |
---|
164 | if (strcmp (ldelim, mmdlm2) |
---|
165 | && write (fd, "\n", 1) != 1 |
---|
166 | && write (fd, mmdlm2, count) != count) |
---|
167 | return NOTOK; |
---|
168 | |
---|
169 | return OK; |
---|
170 | } |
---|
171 | |
---|
172 | |
---|
173 | int |
---|
174 | mbx_read (FILE *fp, long pos, struct drop **drops, int noisy) |
---|
175 | { |
---|
176 | register int len, size; |
---|
177 | register long ld1, ld2; |
---|
178 | register char *bp; |
---|
179 | char buffer[BUFSIZ]; |
---|
180 | register struct drop *cp, *dp, *ep, *pp; |
---|
181 | |
---|
182 | pp = (struct drop *) calloc ((size_t) (len = MAXFOLDER), sizeof(*dp)); |
---|
183 | if (pp == NULL) { |
---|
184 | if (noisy) |
---|
185 | admonish (NULL, "unable to allocate drop storage"); |
---|
186 | return NOTOK; |
---|
187 | } |
---|
188 | |
---|
189 | ld1 = (long) strlen (mmdlm1); |
---|
190 | ld2 = (long) strlen (mmdlm2); |
---|
191 | |
---|
192 | fseek (fp, pos, SEEK_SET); |
---|
193 | for (ep = (dp = pp) + len - 1; fgets (buffer, sizeof(buffer), fp);) { |
---|
194 | size = 0; |
---|
195 | if (strcmp (buffer, mmdlm1) == 0) |
---|
196 | pos += ld1, dp->d_start = (long) pos; |
---|
197 | else { |
---|
198 | dp->d_start = (long)pos , pos += (long) strlen (buffer); |
---|
199 | for (bp = buffer; *bp; bp++, size++) |
---|
200 | if (*bp == '\n') |
---|
201 | size++; |
---|
202 | } |
---|
203 | |
---|
204 | while (fgets (buffer, sizeof(buffer), fp) != NULL) |
---|
205 | if (strcmp (buffer, mmdlm2) == 0) |
---|
206 | break; |
---|
207 | else { |
---|
208 | pos += (long) strlen (buffer); |
---|
209 | for (bp = buffer; *bp; bp++, size++) |
---|
210 | if (*bp == '\n') |
---|
211 | size++; |
---|
212 | } |
---|
213 | |
---|
214 | if (dp->d_start != (long) pos) { |
---|
215 | dp->d_id = 0; |
---|
216 | dp->d_size = (long) size; |
---|
217 | dp->d_stop = pos; |
---|
218 | dp++; |
---|
219 | } |
---|
220 | pos += ld2; |
---|
221 | |
---|
222 | if (dp >= ep) { |
---|
223 | register int curlen = dp - pp; |
---|
224 | |
---|
225 | cp = (struct drop *) realloc ((char *) pp, |
---|
226 | (size_t) (len += MAXFOLDER) * sizeof(*pp)); |
---|
227 | if (cp == NULL) { |
---|
228 | if (noisy) |
---|
229 | admonish (NULL, "unable to allocate drop storage"); |
---|
230 | free ((char *) pp); |
---|
231 | return 0; |
---|
232 | } |
---|
233 | dp = cp + curlen, ep = (pp = cp) + len - 1; |
---|
234 | } |
---|
235 | } |
---|
236 | |
---|
237 | if (dp == pp) |
---|
238 | free ((char *) pp); |
---|
239 | else |
---|
240 | *drops = pp; |
---|
241 | return (dp - pp); |
---|
242 | } |
---|
243 | |
---|
244 | |
---|
245 | int |
---|
246 | mbx_write(char *mailbox, int md, FILE *fp, int id, long last, |
---|
247 | long pos, off_t stop, int mapping, int noisy) |
---|
248 | { |
---|
249 | register int i, j, size; |
---|
250 | off_t start; |
---|
251 | long off; |
---|
252 | register char *cp; |
---|
253 | char buffer[BUFSIZ]; |
---|
254 | |
---|
255 | off = (long) lseek (md, (off_t) 0, SEEK_CUR); |
---|
256 | j = strlen (mmdlm1); |
---|
257 | if (write (md, mmdlm1, j) != j) |
---|
258 | return NOTOK; |
---|
259 | start = lseek (md, (off_t) 0, SEEK_CUR); |
---|
260 | size = 0; |
---|
261 | |
---|
262 | fseek (fp, pos, SEEK_SET); |
---|
263 | while (fgets (buffer, sizeof(buffer), fp) && (pos < stop)) { |
---|
264 | i = strlen (buffer); |
---|
265 | for (j = 0; (j = stringdex (mmdlm1, buffer)) >= 0; buffer[j]++) |
---|
266 | continue; |
---|
267 | for (j = 0; (j = stringdex (mmdlm2, buffer)) >= 0; buffer[j]++) |
---|
268 | continue; |
---|
269 | if (write (md, buffer, i) != i) |
---|
270 | return NOTOK; |
---|
271 | pos += (long) i; |
---|
272 | if (mapping) |
---|
273 | for (cp = buffer; i-- > 0; size++) |
---|
274 | if (*cp++ == '\n') |
---|
275 | size++; |
---|
276 | } |
---|
277 | |
---|
278 | stop = lseek (md, (off_t) 0, SEEK_CUR); |
---|
279 | j = strlen (mmdlm2); |
---|
280 | if (write (md, mmdlm2, j) != j) |
---|
281 | return NOTOK; |
---|
282 | if (mapping) |
---|
283 | map_write (mailbox, md, id, last, start, stop, off, size, noisy); |
---|
284 | |
---|
285 | return OK; |
---|
286 | } |
---|
287 | |
---|
288 | |
---|
289 | /* |
---|
290 | * Append message to end of file or maildrop. |
---|
291 | */ |
---|
292 | |
---|
293 | int |
---|
294 | mbx_copy (char *mailbox, int mbx_style, int md, int fd, |
---|
295 | int mapping, char *text, int noisy) |
---|
296 | { |
---|
297 | int i, j, size; |
---|
298 | off_t start, stop; |
---|
299 | long pos; |
---|
300 | char *cp, buffer[BUFSIZ]; |
---|
301 | FILE *fp; |
---|
302 | |
---|
303 | pos = (long) lseek (md, (off_t) 0, SEEK_CUR); |
---|
304 | size = 0; |
---|
305 | |
---|
306 | switch (mbx_style) { |
---|
307 | case MMDF_FORMAT: |
---|
308 | default: |
---|
309 | j = strlen (mmdlm1); |
---|
310 | if (write (md, mmdlm1, j) != j) |
---|
311 | return NOTOK; |
---|
312 | start = lseek (md, (off_t) 0, SEEK_CUR); |
---|
313 | |
---|
314 | if (text) { |
---|
315 | i = strlen (text); |
---|
316 | if (write (md, text, i) != i) |
---|
317 | return NOTOK; |
---|
318 | for (cp = text; *cp++; size++) |
---|
319 | if (*cp == '\n') |
---|
320 | size++; |
---|
321 | } |
---|
322 | |
---|
323 | while ((i = read (fd, buffer, sizeof(buffer))) > 0) { |
---|
324 | for (j = 0; |
---|
325 | (j = stringdex (mmdlm1, buffer)) >= 0; |
---|
326 | buffer[j]++) |
---|
327 | continue; |
---|
328 | for (j = 0; |
---|
329 | (j = stringdex (mmdlm2, buffer)) >= 0; |
---|
330 | buffer[j]++) |
---|
331 | continue; |
---|
332 | if (write (md, buffer, i) != i) |
---|
333 | return NOTOK; |
---|
334 | if (mapping) |
---|
335 | for (cp = buffer; i-- > 0; size++) |
---|
336 | if (*cp++ == '\n') |
---|
337 | size++; |
---|
338 | } |
---|
339 | |
---|
340 | stop = lseek (md, (off_t) 0, SEEK_CUR); |
---|
341 | j = strlen (mmdlm2); |
---|
342 | if (write (md, mmdlm2, j) != j) |
---|
343 | return NOTOK; |
---|
344 | if (mapping) |
---|
345 | map_write (mailbox, md, 0, (long) 0, start, stop, pos, size, noisy); |
---|
346 | |
---|
347 | return (i != NOTOK ? OK : NOTOK); |
---|
348 | |
---|
349 | case MBOX_FORMAT: |
---|
350 | if ((j = dup (fd)) == NOTOK) |
---|
351 | return NOTOK; |
---|
352 | if ((fp = fdopen (j, "r")) == NULL) { |
---|
353 | close (j); |
---|
354 | return NOTOK; |
---|
355 | } |
---|
356 | start = lseek (md, (off_t) 0, SEEK_CUR); |
---|
357 | |
---|
358 | /* If text is given, we add it to top of message */ |
---|
359 | if (text) { |
---|
360 | i = strlen (text); |
---|
361 | if (write (md, text, i) != i) |
---|
362 | return NOTOK; |
---|
363 | for (cp = text; *cp++; size++) |
---|
364 | if (*cp == '\n') |
---|
365 | size++; |
---|
366 | } |
---|
367 | |
---|
368 | for (j = 0; fgets (buffer, sizeof(buffer), fp) != NULL; j++) { |
---|
369 | |
---|
370 | /* |
---|
371 | * Check the first line, and make some changes. |
---|
372 | */ |
---|
373 | if (j == 0 && !text) { |
---|
374 | /* |
---|
375 | * Change the "Return-Path:" field (if in first line) |
---|
376 | * back to "From ". |
---|
377 | */ |
---|
378 | if (!strncmp (buffer, "Return-Path:", 12)) { |
---|
379 | char tmpbuffer[BUFSIZ]; |
---|
380 | char *tp, *ep, *fp; |
---|
381 | |
---|
382 | strncpy(tmpbuffer, buffer, sizeof(tmpbuffer)); |
---|
383 | ep = tmpbuffer + 13; |
---|
384 | if (!(fp = strchr(ep + 1, ' '))) |
---|
385 | fp = strchr(ep + 1, '\n'); |
---|
386 | tp = dctime(dlocaltimenow()); |
---|
387 | snprintf (buffer, sizeof(buffer), "From %.*s %s", |
---|
388 | fp - ep, ep, tp); |
---|
389 | } else if (!strncmp (buffer, "X-Envelope-From:", 16)) { |
---|
390 | /* |
---|
391 | * Change the "X-Envelope-From:" field |
---|
392 | * (if first line) back to "From ". |
---|
393 | */ |
---|
394 | char tmpbuffer[BUFSIZ]; |
---|
395 | char *ep; |
---|
396 | |
---|
397 | strncpy(tmpbuffer, buffer, sizeof(tmpbuffer)); |
---|
398 | ep = tmpbuffer + 17; |
---|
399 | snprintf (buffer, sizeof(buffer), "From %s", ep); |
---|
400 | } else if (strncmp (buffer, "From ", 5)) { |
---|
401 | /* |
---|
402 | * If there is already a "From " line, |
---|
403 | * then leave it alone. Else we add one. |
---|
404 | */ |
---|
405 | char tmpbuffer[BUFSIZ]; |
---|
406 | char *tp, *ep; |
---|
407 | |
---|
408 | strncpy(tmpbuffer, buffer, sizeof(tmpbuffer)); |
---|
409 | ep = "nobody@nowhere"; |
---|
410 | tp = dctime(dlocaltimenow()); |
---|
411 | snprintf (buffer, sizeof(buffer), "From %s %s", ep, tp); |
---|
412 | strcat (buffer, tmpbuffer); |
---|
413 | } |
---|
414 | } |
---|
415 | |
---|
416 | /* |
---|
417 | * If this is not first line, and begins with |
---|
418 | * "From ", then prepend line with ">". |
---|
419 | */ |
---|
420 | if (j != 0 && strncmp (buffer, "From ", 5) == 0) { |
---|
421 | write (md, ">", 1); |
---|
422 | size++; |
---|
423 | } |
---|
424 | i = strlen (buffer); |
---|
425 | if (write (md, buffer, i) != i) { |
---|
426 | fclose (fp); |
---|
427 | return NOTOK; |
---|
428 | } |
---|
429 | if (mapping) |
---|
430 | for (cp = buffer; i-- > 0; size++) |
---|
431 | if (*cp++ == '\n') |
---|
432 | size++; |
---|
433 | } |
---|
434 | if (write (md, "\n", 1) != 1) { |
---|
435 | fclose (fp); |
---|
436 | return NOTOK; |
---|
437 | } |
---|
438 | if (mapping) |
---|
439 | size += 2; |
---|
440 | |
---|
441 | fclose (fp); |
---|
442 | lseek (fd, (off_t) 0, SEEK_END); |
---|
443 | stop = lseek (md, (off_t) 0, SEEK_CUR); |
---|
444 | if (mapping) |
---|
445 | map_write (mailbox, md, 0, (long) 0, start, stop, pos, size, noisy); |
---|
446 | |
---|
447 | return OK; |
---|
448 | } |
---|
449 | } |
---|
450 | |
---|
451 | |
---|
452 | int |
---|
453 | mbx_size (int md, off_t start, off_t stop) |
---|
454 | { |
---|
455 | register int i, fd; |
---|
456 | register long pos; |
---|
457 | register FILE *fp; |
---|
458 | |
---|
459 | if ((fd = dup (md)) == NOTOK || (fp = fdopen (fd, "r")) == NULL) { |
---|
460 | if (fd != NOTOK) |
---|
461 | close (fd); |
---|
462 | return NOTOK; |
---|
463 | } |
---|
464 | |
---|
465 | fseek (fp, start, SEEK_SET); |
---|
466 | for (i = 0, pos = stop - start; pos-- > 0; i++) |
---|
467 | if (fgetc (fp) == '\n') |
---|
468 | i++; |
---|
469 | |
---|
470 | fclose (fp); |
---|
471 | return i; |
---|
472 | } |
---|
473 | |
---|
474 | |
---|
475 | /* |
---|
476 | * Close and unlock file/maildrop. |
---|
477 | */ |
---|
478 | |
---|
479 | int |
---|
480 | mbx_close (char *mailbox, int md) |
---|
481 | { |
---|
482 | return (lkclose (md, mailbox) == 0 ? OK : NOTOK); |
---|
483 | } |
---|
484 | |
---|
485 | |
---|
486 | /* |
---|
487 | * This function is performed implicitly by getbbent.c: |
---|
488 | * bb->bb_map = map_name (bb->bb_file); |
---|
489 | */ |
---|
490 | |
---|
491 | char * |
---|
492 | map_name (char *file) |
---|
493 | { |
---|
494 | register char *cp, *dp; |
---|
495 | static char buffer[BUFSIZ]; |
---|
496 | |
---|
497 | if ((dp = strchr(cp = r1bindex (file, '/'), '.')) == NULL) |
---|
498 | dp = cp + strlen (cp); |
---|
499 | if (cp == file) |
---|
500 | snprintf (buffer, sizeof(buffer), ".%.*s%s", dp - cp, cp, ".map"); |
---|
501 | else |
---|
502 | snprintf (buffer, sizeof(buffer), "%.*s.%.*s%s", |
---|
503 | cp - file, file, dp - cp, cp, ".map"); |
---|
504 | |
---|
505 | return buffer; |
---|
506 | } |
---|
507 | |
---|
508 | |
---|
509 | int |
---|
510 | map_read (char *file, long pos, struct drop **drops, int noisy) |
---|
511 | { |
---|
512 | register int i, md, msgp; |
---|
513 | register char *cp; |
---|
514 | struct drop d; |
---|
515 | register struct drop *mp, *dp; |
---|
516 | |
---|
517 | if ((md = open (cp = map_name (file), O_RDONLY)) == NOTOK |
---|
518 | || map_chk (cp, md, mp = &d, pos, noisy)) { |
---|
519 | if (md != NOTOK) |
---|
520 | close (md); |
---|
521 | return 0; |
---|
522 | } |
---|
523 | |
---|
524 | msgp = mp->d_id; |
---|
525 | dp = (struct drop *) calloc ((size_t) (msgp + 1), sizeof(*dp)); |
---|
526 | if (dp == NULL) { |
---|
527 | close (md); |
---|
528 | return 0; |
---|
529 | } |
---|
530 | |
---|
531 | memcpy((char *) dp, (char *) mp, sizeof(*dp)); |
---|
532 | |
---|
533 | lseek (md, (off_t) sizeof(*mp), SEEK_SET); |
---|
534 | if ((i = read (md, (char *) (dp + 1), msgp * sizeof(*dp))) < sizeof(*dp)) { |
---|
535 | i = 0; |
---|
536 | free ((char *) dp); |
---|
537 | } else { |
---|
538 | #ifdef NTOHLSWAP |
---|
539 | register struct drop *tdp; |
---|
540 | int j; |
---|
541 | |
---|
542 | for (j = 0, tdp = dp; j < i / sizeof(*dp); j++, tdp++) { |
---|
543 | tdp->d_id = ntohl(tdp->d_id); |
---|
544 | tdp->d_size = ntohl(tdp->d_size); |
---|
545 | tdp->d_start = ntohl(tdp->d_start); |
---|
546 | tdp->d_stop = ntohl(tdp->d_stop); |
---|
547 | } |
---|
548 | #endif |
---|
549 | *drops = dp; |
---|
550 | } |
---|
551 | |
---|
552 | close (md); |
---|
553 | |
---|
554 | return (i / sizeof(*dp)); |
---|
555 | } |
---|
556 | |
---|
557 | |
---|
558 | int |
---|
559 | map_write (char *mailbox, int md, int id, long last, off_t start, |
---|
560 | off_t stop, long pos, int size, int noisy) |
---|
561 | { |
---|
562 | register int i; |
---|
563 | int clear, fd, td; |
---|
564 | char *file; |
---|
565 | register struct drop *dp; |
---|
566 | struct drop d1, d2, *rp; |
---|
567 | register FILE *fp; |
---|
568 | |
---|
569 | if ((fd = map_open (file = map_name (mailbox), &clear, md)) == NOTOK) |
---|
570 | return NOTOK; |
---|
571 | |
---|
572 | if (!clear && map_chk (file, fd, &d1, pos, noisy)) { |
---|
573 | unlink (file); |
---|
574 | mbx_close (file, fd); |
---|
575 | if ((fd = map_open (file, &clear, md)) == NOTOK) |
---|
576 | return NOTOK; |
---|
577 | clear++; |
---|
578 | } |
---|
579 | |
---|
580 | if (clear) { |
---|
581 | if ((td = dup (md)) == NOTOK || (fp = fdopen (td, "r")) == NULL) { |
---|
582 | if (noisy) |
---|
583 | admonish (file, "unable to %s", td != NOTOK ? "fdopen" : "dup"); |
---|
584 | if (td != NOTOK) |
---|
585 | close (td); |
---|
586 | mbx_close (file, fd); |
---|
587 | return NOTOK; |
---|
588 | } |
---|
589 | |
---|
590 | switch (i = mbx_read (fp, 0, &rp, noisy)) { |
---|
591 | case NOTOK: |
---|
592 | fclose (fp); |
---|
593 | mbx_close (file, fd); |
---|
594 | return NOTOK; |
---|
595 | |
---|
596 | case OK: |
---|
597 | break; |
---|
598 | |
---|
599 | default: |
---|
600 | d1.d_id = 0; |
---|
601 | for (dp = rp; i-- >0; dp++) { |
---|
602 | if (dp->d_start == start) |
---|
603 | dp->d_id = id; |
---|
604 | lseek (fd, (off_t) (++d1.d_id * sizeof(*dp)), SEEK_SET); |
---|
605 | if (write (fd, (char *) dp, sizeof(*dp)) != sizeof(*dp)) { |
---|
606 | if (noisy) |
---|
607 | admonish (file, "write error"); |
---|
608 | mbx_close (file, fd); |
---|
609 | fclose (fp); |
---|
610 | return NOTOK; |
---|
611 | } |
---|
612 | } |
---|
613 | free ((char *) rp); |
---|
614 | break; |
---|
615 | } |
---|
616 | } |
---|
617 | else { |
---|
618 | if (last == 0) |
---|
619 | last = d1.d_start; |
---|
620 | dp = &d2; |
---|
621 | dp->d_id = id; |
---|
622 | dp->d_size = (long) (size ? size : mbx_size (fd, start, stop)); |
---|
623 | dp->d_start = start; |
---|
624 | dp->d_stop = stop; |
---|
625 | lseek (fd, (off_t) (++d1.d_id * sizeof(*dp)), SEEK_SET); |
---|
626 | if (write (fd, (char *) dp, sizeof(*dp)) != sizeof(*dp)) { |
---|
627 | if (noisy) |
---|
628 | admonish (file, "write error"); |
---|
629 | mbx_close (file, fd); |
---|
630 | return NOTOK; |
---|
631 | } |
---|
632 | } |
---|
633 | |
---|
634 | dp = &d1; |
---|
635 | dp->d_size = DRVRSN; |
---|
636 | dp->d_start = (long) last; |
---|
637 | dp->d_stop = lseek (md, (off_t) 0, SEEK_CUR); |
---|
638 | |
---|
639 | lseek (fd, (off_t) 0, SEEK_SET); |
---|
640 | if (write (fd, (char *) dp, sizeof(*dp)) != sizeof(*dp)) { |
---|
641 | if (noisy) |
---|
642 | admonish (file, "write error"); |
---|
643 | mbx_close (file, fd); |
---|
644 | return NOTOK; |
---|
645 | } |
---|
646 | |
---|
647 | if (mbx_close (file, fd) == NOTOK) |
---|
648 | return NOTOK; |
---|
649 | |
---|
650 | return OK; |
---|
651 | } |
---|
652 | |
---|
653 | |
---|
654 | static int |
---|
655 | map_open (char *file, int *clear, int md) |
---|
656 | { |
---|
657 | mode_t mode; |
---|
658 | struct stat st; |
---|
659 | |
---|
660 | mode = fstat (md, &st) != NOTOK ? (mode_t) (st.st_mode & 0777) : m_gmprot (); |
---|
661 | return mbx_open (file, OTHER_FORMAT, st.st_uid, st.st_gid, mode); |
---|
662 | } |
---|
663 | |
---|
664 | |
---|
665 | int |
---|
666 | map_chk (char *file, int fd, struct drop *dp, long pos, int noisy) |
---|
667 | { |
---|
668 | long count; |
---|
669 | struct drop d, tmpd; |
---|
670 | register struct drop *dl; |
---|
671 | |
---|
672 | if (read (fd, (char *) &tmpd, sizeof(*dp)) != sizeof(*dp)) { |
---|
673 | #ifdef notdef |
---|
674 | admonish (NULL, "%s: missing or partial index", file); |
---|
675 | #endif /* notdef */ |
---|
676 | return NOTOK; |
---|
677 | } |
---|
678 | #ifndef NTOHLSWAP |
---|
679 | *dp = tmpd; /* if ntohl(n)=(n), can use struct assign */ |
---|
680 | #else |
---|
681 | dp->d_id = ntohl(tmpd.d_id); |
---|
682 | dp->d_size = ntohl(tmpd.d_size); |
---|
683 | dp->d_start = ntohl(tmpd.d_start); |
---|
684 | dp->d_stop = ntohl(tmpd.d_stop); |
---|
685 | #endif |
---|
686 | |
---|
687 | if (dp->d_size != DRVRSN) { |
---|
688 | if (noisy) |
---|
689 | admonish (NULL, "%s: version mismatch (%d != %d)", file, |
---|
690 | dp->d_size, DRVRSN); |
---|
691 | return NOTOK; |
---|
692 | } |
---|
693 | |
---|
694 | if (dp->d_stop != pos) { |
---|
695 | if (noisy && pos != (long) 0) |
---|
696 | admonish (NULL, |
---|
697 | "%s: pointer mismatch or incomplete index (%ld!=%ld)", |
---|
698 | file, dp->d_stop, (long) pos); |
---|
699 | return NOTOK; |
---|
700 | } |
---|
701 | |
---|
702 | if ((long) ((dp->d_id + 1) * sizeof(*dp)) != (long) lseek (fd, (off_t) 0, SEEK_END)) { |
---|
703 | if (noisy) |
---|
704 | admonish (NULL, "%s: corrupt index(1)", file); |
---|
705 | return NOTOK; |
---|
706 | } |
---|
707 | |
---|
708 | dl = &d; |
---|
709 | count = (long) strlen (mmdlm2); |
---|
710 | lseek (fd, (off_t) (dp->d_id * sizeof(*dp)), SEEK_SET); |
---|
711 | if (read (fd, (char *) dl, sizeof(*dl)) != sizeof(*dl) |
---|
712 | || (ntohl(dl->d_stop) != dp->d_stop |
---|
713 | && ntohl(dl->d_stop) + count != dp->d_stop)) { |
---|
714 | if (noisy) |
---|
715 | admonish (NULL, "%s: corrupt index(2)", file); |
---|
716 | return NOTOK; |
---|
717 | } |
---|
718 | |
---|
719 | return OK; |
---|
720 | } |
---|