3 * Memory buffer operations.
5 * Copyright (c) 2005 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * contrib/pgcrypto/mbuf.c
37 #define STEP (16*1024)
50 mbuf_avail(MBuf
*mbuf
)
52 return mbuf
->data_end
- mbuf
->read_pos
;
58 return mbuf
->data_end
- mbuf
->data
;
64 return mbuf
->read_pos
- mbuf
->data
;
72 px_memset(mbuf
->data
, 0, mbuf
->buf_end
- mbuf
->data
);
80 prepare_room(MBuf
*mbuf
, int block_len
)
85 if (mbuf
->data_end
+ block_len
<= mbuf
->buf_end
)
88 newlen
= (mbuf
->buf_end
- mbuf
->data
)
89 + ((block_len
+ STEP
+ STEP
- 1) & -STEP
);
91 newbuf
= repalloc(mbuf
->data
, newlen
);
93 mbuf
->buf_end
= newbuf
+ newlen
;
94 mbuf
->data_end
= newbuf
+ (mbuf
->data_end
- mbuf
->data
);
95 mbuf
->read_pos
= newbuf
+ (mbuf
->read_pos
- mbuf
->data
);
100 mbuf_append(MBuf
*dst
, const uint8
*buf
, int len
)
104 px_debug("mbuf_append: no_write");
108 prepare_room(dst
, len
);
110 memcpy(dst
->data_end
, buf
, len
);
111 dst
->data_end
+= len
;
124 mbuf
= palloc(sizeof *mbuf
);
125 mbuf
->data
= palloc(len
);
126 mbuf
->buf_end
= mbuf
->data
+ len
;
127 mbuf
->data_end
= mbuf
->data
;
128 mbuf
->read_pos
= mbuf
->data
;
130 mbuf
->no_write
= false;
131 mbuf
->own_data
= true;
137 mbuf_create_from_data(uint8
*data
, int len
)
141 mbuf
= palloc(sizeof *mbuf
);
142 mbuf
->data
= (uint8
*) data
;
143 mbuf
->buf_end
= mbuf
->data
+ len
;
144 mbuf
->data_end
= mbuf
->data
+ len
;
145 mbuf
->read_pos
= mbuf
->data
;
147 mbuf
->no_write
= true;
148 mbuf
->own_data
= false;
155 mbuf_grab(MBuf
*mbuf
, int len
, uint8
**data_p
)
157 if (len
> mbuf_avail(mbuf
))
158 len
= mbuf_avail(mbuf
);
160 mbuf
->no_write
= true;
162 *data_p
= mbuf
->read_pos
;
163 mbuf
->read_pos
+= len
;
168 mbuf_rewind(MBuf
*mbuf
)
170 mbuf
->read_pos
= mbuf
->data
;
175 mbuf_steal_data(MBuf
*mbuf
, uint8
**data_p
)
177 int len
= mbuf_size(mbuf
);
179 mbuf
->no_write
= true;
180 mbuf
->own_data
= false;
182 *data_p
= mbuf
->data
;
184 mbuf
->data
= mbuf
->data_end
= mbuf
->read_pos
= mbuf
->buf_end
= NULL
;
196 const PullFilterOps
*op
;
204 pullf_create(PullFilter
**pf_p
, const PullFilterOps
*op
, void *init_arg
, PullFilter
*src
)
210 if (op
->init
!= NULL
)
212 res
= op
->init(&priv
, init_arg
, src
);
222 pf
= palloc0(sizeof(*pf
));
229 pf
->buf
= palloc(pf
->buflen
);
242 pullf_free(PullFilter
*pf
)
245 pf
->op
->free(pf
->priv
);
249 px_memset(pf
->buf
, 0, pf
->buflen
);
253 px_memset(pf
, 0, sizeof(*pf
));
257 /* may return less data than asked, 0 means eof */
259 pullf_read(PullFilter
*pf
, int len
, uint8
**data_p
)
265 if (pf
->buflen
&& len
> pf
->buflen
)
267 res
= pf
->op
->pull(pf
->priv
, pf
->src
, len
, data_p
,
268 pf
->buf
, pf
->buflen
);
271 res
= pullf_read(pf
->src
, len
, data_p
);
276 pullf_read_max(PullFilter
*pf
, int len
, uint8
**data_p
, uint8
*tmpbuf
)
282 res
= pullf_read(pf
, len
, data_p
);
283 if (res
<= 0 || res
== len
)
286 /* read was shorter, use tmpbuf */
287 memcpy(tmpbuf
, *data_p
, res
);
294 res
= pullf_read(pf
, len
, &tmp
);
297 /* so the caller must clear only on success */
298 px_memset(tmpbuf
, 0, total
);
303 memcpy(tmpbuf
+ total
, tmp
, res
);
311 * caller wants exactly len bytes and don't bother with references
314 pullf_read_fixed(PullFilter
*src
, int len
, uint8
*dst
)
319 res
= pullf_read_max(src
, len
, &p
, dst
);
324 px_debug("pullf_read_fixed: need=%d got=%d", len
, res
);
325 return PXE_PGP_CORRUPT_DATA
;
336 pull_from_mbuf(void *arg
, PullFilter
*src
, int len
,
337 uint8
**data_p
, uint8
*buf
, int buflen
)
341 return mbuf_grab(mbuf
, len
, data_p
);
344 static const struct PullFilterOps mbuf_reader
= {
345 NULL
, pull_from_mbuf
, NULL
349 pullf_create_mbuf_reader(PullFilter
**mp_p
, MBuf
*src
)
351 return pullf_create(mp_p
, &mbuf_reader
, src
, NULL
);
362 const PushFilterOps
*op
;
370 pushf_create(PushFilter
**mp_p
, const PushFilterOps
*op
, void *init_arg
, PushFilter
*next
)
376 if (op
->init
!= NULL
)
378 res
= op
->init(next
, init_arg
, &priv
);
388 mp
= palloc0(sizeof(*mp
));
389 mp
->block_size
= res
;
393 if (mp
->block_size
> 0)
395 mp
->buf
= palloc(mp
->block_size
);
408 pushf_free(PushFilter
*mp
)
411 mp
->op
->free(mp
->priv
);
415 px_memset(mp
->buf
, 0, mp
->block_size
);
419 px_memset(mp
, 0, sizeof(*mp
));
424 pushf_free_all(PushFilter
*mp
)
437 wrap_process(PushFilter
*mp
, const uint8
*data
, int len
)
441 if (mp
->op
->push
!= NULL
)
442 res
= mp
->op
->push(mp
->next
, mp
->priv
, data
, len
);
444 res
= pushf_write(mp
->next
, data
, len
);
450 /* consumes all data, returns len on success */
452 pushf_write(PushFilter
*mp
, const uint8
*data
, int len
)
460 if (mp
->block_size
<= 0)
461 return wrap_process(mp
, data
, len
);
464 * try to empty buffer
466 need
= mp
->block_size
- mp
->pos
;
471 memcpy(mp
->buf
+ mp
->pos
, data
, len
);
475 memcpy(mp
->buf
+ mp
->pos
, data
, need
);
481 * buffer full, process
483 res
= wrap_process(mp
, mp
->buf
, mp
->block_size
);
489 * now process directly from data
493 if (len
> mp
->block_size
)
495 res
= wrap_process(mp
, data
, mp
->block_size
);
498 data
+= mp
->block_size
;
499 len
-= mp
->block_size
;
503 memcpy(mp
->buf
, data
, len
);
512 pushf_flush(PushFilter
*mp
)
518 if (mp
->block_size
> 0)
520 res
= wrap_process(mp
, mp
->buf
, mp
->pos
);
527 res
= mp
->op
->flush(mp
->next
, mp
->priv
);
542 push_into_mbuf(PushFilter
*next
, void *arg
, const uint8
*data
, int len
)
548 res
= mbuf_append(mbuf
, data
, len
);
549 return res
< 0 ? res
: 0;
552 static const struct PushFilterOps mbuf_filter
= {
553 NULL
, push_into_mbuf
, NULL
, NULL
557 pushf_create_mbuf_writer(PushFilter
**res
, MBuf
*dst
)
559 return pushf_create(res
, &mbuf_filter
, dst
, NULL
);