No empty .Rs/.Re
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / cleanup / cleanup_body_edit.c
blobb41341e9b987d0b16c512f5dd312480ce81a9383
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* cleanup_body_edit 3
6 /* SUMMARY
7 /* edit body content
8 /* SYNOPSIS
9 /* #include "cleanup.h"
11 /* int cleanup_body_edit_start(state)
12 /* CLEANUP_STATE *state;
14 /* int cleanup_body_edit_write(state, type, buf)
15 /* CLEANUP_STATE *state;
16 /* int type;
17 /* VSTRING *buf;
19 /* int cleanup_body_edit_finish(state)
20 /* CLEANUP_STATE *state;
22 /* void cleanup_body_edit_free(state)
23 /* CLEANUP_STATE *state;
24 /* DESCRIPTION
25 /* This module maintains queue file regions with body content.
26 /* Regions are created on the fly, and can be reused multiple
27 /* times. This module must not be called until the queue file
28 /* is complete, and there must be no other read/write access
29 /* to the queue file between the cleanup_body_edit_start() and
30 /* cleanup_body_edit_finish() calls.
32 /* cleanup_body_edit_start() performs initialization and sets
33 /* the queue file write pointer to the start of the first body
34 /* region.
36 /* cleanup_body_edit_write() adds a queue file record to the
37 /* queue file. When the current body region fills up, some
38 /* unused region is reused, or a new region is created.
40 /* cleanup_body_edit_finish() makes some final adjustments
41 /* after the last body content record is written.
43 /* cleanup_body_edit_free() frees up memory that was allocated
44 /* by cleanup_body_edit_start() and cleanup_body_edit_write().
46 /* Arguments:
47 /* .IP state
48 /* Queue file and message processing state. This state is updated
49 /* as records are processed and as errors happen.
50 /* .IP type
51 /* Record type.
52 /* .IP buf
53 /* Record content.
54 /* LICENSE
55 /* .ad
56 /* .fi
57 /* The Secure Mailer license must be distributed with this software.
58 /* AUTHOR(S)
59 /* Wietse Venema
60 /* IBM T.J. Watson Research
61 /* P.O. Box 704
62 /* Yorktown Heights, NY 10598, USA
63 /*--*/
65 /* System library. */
67 #include <sys_defs.h>
69 /* Utility library. */
71 #include <msg.h>
72 #include <mymalloc.h>
73 #include <vstream.h>
74 #include <vstring.h>
76 /* Global library. */
78 #include <rec_type.h>
79 #include <record.h>
81 /* Application-specific. */
83 #include <cleanup.h>
85 #define LEN(s) VSTRING_LEN(s)
87 static int cleanup_body_edit_ptr_rec_len;
89 /* cleanup_body_edit_start - rewrite body region pool */
91 int cleanup_body_edit_start(CLEANUP_STATE *state)
93 const char *myname = "cleanup_body_edit_start";
94 CLEANUP_REGION *curr_rp;
97 * Calculate the payload size sans body.
99 state->cont_length = state->body_offset - state->data_offset;
102 * One-time initialization.
104 if (state->body_regions == 0) {
105 REC_SPACE_NEED(REC_TYPE_PTR_PAYL_SIZE, cleanup_body_edit_ptr_rec_len);
106 cleanup_region_init(state);
110 * Return all body regions to the free pool.
112 cleanup_region_return(state, state->body_regions);
115 * Select the first region. XXX This will usally be the original body
116 * segment, but we must not count on that. Region assignments may change
117 * when header editing also uses queue file regions. XXX We don't really
118 * know if the first region will be large enough to hold the first body
119 * text record, but this problem is so rare that we will not complicate
120 * the code for it. If the first region is too small then we will simply
121 * waste it.
123 curr_rp = state->curr_body_region = state->body_regions =
124 cleanup_region_open(state, cleanup_body_edit_ptr_rec_len);
127 * Link the first body region to the last message header.
129 if (vstream_fseek(state->dst, state->append_hdr_pt_offset, SEEK_SET) < 0) {
130 msg_warn("%s: seek file %s: %m", myname, cleanup_path);
131 return (-1);
133 state->append_hdr_pt_target = curr_rp->start;
134 rec_fprintf(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT,
135 (long) state->append_hdr_pt_target);
138 * Move the file write pointer to the start of the current region.
140 if (vstream_ftell(state->dst) != curr_rp->start
141 && vstream_fseek(state->dst, curr_rp->start, SEEK_SET) < 0) {
142 msg_warn("%s: seek file %s: %m", myname, cleanup_path);
143 return (-1);
145 return (0);
148 /* cleanup_body_edit_write - add record to body region pool */
150 int cleanup_body_edit_write(CLEANUP_STATE *state, int rec_type,
151 VSTRING *buf)
153 const char *myname = "cleanup_body_edit_write";
154 CLEANUP_REGION *curr_rp = state->curr_body_region;
155 CLEANUP_REGION *next_rp;
156 off_t space_used;
157 ssize_t space_needed;
158 ssize_t rec_len;
160 if (msg_verbose)
161 msg_info("%s: where %ld, buflen %ld region start %ld len %ld",
162 myname, (long) curr_rp->write_offs, (long) LEN(buf),
163 (long) curr_rp->start, (long) curr_rp->len);
166 * Switch to the next body region if we filled up the current one (we
167 * always append to an open-ended region). Besides space to write the
168 * specified record, we need to leave space for a final pointer record
169 * that will link this body region to the next region or to the content
170 * terminator record.
172 if (curr_rp->len > 0) {
173 space_used = curr_rp->write_offs - curr_rp->start;
174 REC_SPACE_NEED(LEN(buf), rec_len);
175 space_needed = rec_len + cleanup_body_edit_ptr_rec_len;
176 if (space_needed > curr_rp->len - space_used) {
179 * Update the payload size. Connect the filled up body region to
180 * its successor.
182 state->cont_length += space_used;
183 next_rp = cleanup_region_open(state, space_needed);
184 if (msg_verbose)
185 msg_info("%s: link %ld -> %ld", myname,
186 (long) curr_rp->write_offs, (long) next_rp->start);
187 rec_fprintf(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT,
188 (long) next_rp->start);
189 curr_rp->write_offs = vstream_ftell(state->dst);
190 cleanup_region_close(state, curr_rp);
191 curr_rp->next = next_rp;
194 * Select the new body region.
196 state->curr_body_region = curr_rp = next_rp;
197 if (vstream_fseek(state->dst, curr_rp->start, SEEK_SET) < 0) {
198 msg_warn("%s: seek file %s: %m", myname, cleanup_path);
199 return (-1);
205 * Finally, output the queue file record.
207 CLEANUP_OUT_BUF(state, REC_TYPE_NORM, buf);
208 curr_rp->write_offs = vstream_ftell(state->dst);
210 return (0);
213 /* cleanup_body_edit_finish - wrap up body region pool */
215 int cleanup_body_edit_finish(CLEANUP_STATE *state)
217 CLEANUP_REGION *curr_rp = state->curr_body_region;
220 * Update the payload size.
222 state->cont_length += curr_rp->write_offs - curr_rp->start;
225 * Link the last body region to the content terminator record.
227 rec_fprintf(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT,
228 (long) state->xtra_offset);
229 curr_rp->write_offs = vstream_ftell(state->dst);
230 cleanup_region_close(state, curr_rp);
232 return (CLEANUP_OUT_OK(state) ? 0 : -1);