Fix bug #42294
[apr-util.git] / buckets / apr_brigade.c
blob332b2bc33e350eef0eefbbd7749306569b73b6b8
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "apr.h"
18 #include "apr_lib.h"
19 #include "apr_strings.h"
20 #include "apr_pools.h"
21 #include "apr_tables.h"
22 #include "apr_buckets.h"
23 #include "apr_errno.h"
24 #define APR_WANT_MEMFUNC
25 #define APR_WANT_STRFUNC
26 #include "apr_want.h"
28 #if APR_HAVE_SYS_UIO_H
29 #include <sys/uio.h>
30 #endif
32 static apr_status_t brigade_cleanup(void *data)
34 return apr_brigade_cleanup(data);
37 APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data)
39 apr_bucket_brigade *b = data;
40 apr_bucket *e;
42 while (!APR_BRIGADE_EMPTY(b)) {
43 e = APR_BRIGADE_FIRST(b);
44 apr_bucket_delete(e);
46 /* We don't need to free(bb) because it's allocated from a pool. */
47 return APR_SUCCESS;
50 APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b)
52 apr_pool_cleanup_kill(b->p, b, brigade_cleanup);
53 return apr_brigade_cleanup(b);
56 APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p,
57 apr_bucket_alloc_t *list)
59 apr_bucket_brigade *b;
61 b = apr_palloc(p, sizeof(*b));
62 b->p = p;
63 b->bucket_alloc = list;
65 APR_RING_INIT(&b->list, apr_bucket, link);
67 apr_pool_cleanup_register(b->p, b, brigade_cleanup, apr_pool_cleanup_null);
68 return b;
71 APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
72 apr_bucket *e)
74 apr_bucket_brigade *a;
75 apr_bucket *f;
77 a = apr_brigade_create(b->p, b->bucket_alloc);
78 /* Return an empty brigade if there is nothing left in
79 * the first brigade to split off
81 if (e != APR_BRIGADE_SENTINEL(b)) {
82 f = APR_RING_LAST(&b->list);
83 APR_RING_UNSPLICE(e, f, link);
84 APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link);
87 APR_BRIGADE_CHECK_CONSISTENCY(a);
88 APR_BRIGADE_CHECK_CONSISTENCY(b);
90 return a;
93 APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
94 apr_off_t point,
95 apr_bucket **after_point)
97 apr_bucket *e;
98 const char *s;
99 apr_size_t len;
100 apr_status_t rv;
102 if (point < 0) {
103 /* this could cause weird (not necessarily SEGV) things to happen */
104 return APR_EINVAL;
106 if (point == 0) {
107 *after_point = APR_BRIGADE_FIRST(b);
108 return APR_SUCCESS;
111 APR_BRIGADE_CHECK_CONSISTENCY(b);
113 for (e = APR_BRIGADE_FIRST(b);
114 e != APR_BRIGADE_SENTINEL(b);
115 e = APR_BUCKET_NEXT(e))
117 if ((e->length == (apr_size_t)(-1)) && (point > (apr_size_t)(-1))) {
118 /* point is too far out to simply split this bucket,
119 * we must fix this bucket's size and keep going... */
120 rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
121 if (rv != APR_SUCCESS) {
122 *after_point = e;
123 return rv;
126 if ((point < e->length) || (e->length == (apr_size_t)(-1))) {
127 /* We already checked e->length -1 above, so we now
128 * trust e->length < MAX_APR_SIZE_T.
129 * First try to split the bucket natively... */
130 if ((rv = apr_bucket_split(e, (apr_size_t)point))
131 != APR_ENOTIMPL) {
132 *after_point = APR_BUCKET_NEXT(e);
133 return rv;
136 /* if the bucket cannot be split, we must read from it,
137 * changing its type to one that can be split */
138 rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
139 if (rv != APR_SUCCESS) {
140 *after_point = e;
141 return rv;
144 /* this assumes that len == e->length, which is okay because e
145 * might have been morphed by the apr_bucket_read() above, but
146 * if it was, the length would have been adjusted appropriately */
147 if (point < e->length) {
148 rv = apr_bucket_split(e, (apr_size_t)point);
149 *after_point = APR_BUCKET_NEXT(e);
150 return rv;
153 if (point == e->length) {
154 *after_point = APR_BUCKET_NEXT(e);
155 return APR_SUCCESS;
157 point -= e->length;
159 *after_point = APR_BRIGADE_SENTINEL(b);
160 return APR_INCOMPLETE;
163 APU_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb,
164 int read_all, apr_off_t *length)
166 apr_off_t total = 0;
167 apr_bucket *bkt;
169 for (bkt = APR_BRIGADE_FIRST(bb);
170 bkt != APR_BRIGADE_SENTINEL(bb);
171 bkt = APR_BUCKET_NEXT(bkt))
173 if (bkt->length == (apr_size_t)(-1)) {
174 const char *ignore;
175 apr_size_t len;
176 apr_status_t status;
178 if (!read_all) {
179 *length = -1;
180 return APR_SUCCESS;
183 if ((status = apr_bucket_read(bkt, &ignore, &len,
184 APR_BLOCK_READ)) != APR_SUCCESS) {
185 return status;
189 total += bkt->length;
192 *length = total;
193 return APR_SUCCESS;
196 APU_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb,
197 char *c, apr_size_t *len)
199 apr_size_t actual = 0;
200 apr_bucket *b;
202 for (b = APR_BRIGADE_FIRST(bb);
203 b != APR_BRIGADE_SENTINEL(bb);
204 b = APR_BUCKET_NEXT(b))
206 const char *str;
207 apr_size_t str_len;
208 apr_status_t status;
210 status = apr_bucket_read(b, &str, &str_len, APR_BLOCK_READ);
211 if (status != APR_SUCCESS) {
212 return status;
215 /* If we would overflow. */
216 if (str_len + actual > *len) {
217 str_len = *len - actual;
220 /* XXX: It appears that overflow of the final bucket
221 * is DISCARDED without any warning to the caller.
223 * No, we only copy the data up to their requested size. -- jre
225 memcpy(c, str, str_len);
227 c += str_len;
228 actual += str_len;
230 /* This could probably be actual == *len, but be safe from stray
231 * photons. */
232 if (actual >= *len) {
233 break;
237 *len = actual;
238 return APR_SUCCESS;
241 APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb,
242 char **c,
243 apr_size_t *len,
244 apr_pool_t *pool)
246 apr_off_t actual;
247 apr_size_t total;
248 apr_status_t rv;
250 apr_brigade_length(bb, 1, &actual);
252 /* XXX: This is dangerous beyond belief. At least in the
253 * apr_brigade_flatten case, the user explicitly stated their
254 * buffer length - so we don't up and palloc 4GB for a single
255 * file bucket. This API must grow a useful max boundry,
256 * either compiled-in or preset via the *len value.
258 * Shouldn't both fn's grow an additional return value for
259 * the case that the brigade couldn't be flattened into the
260 * provided or allocated buffer (such as APR_EMOREDATA?)
261 * Not a failure, simply an advisory result.
263 total = (apr_size_t)actual;
265 *c = apr_palloc(pool, total);
267 rv = apr_brigade_flatten(bb, *c, &total);
269 if (rv != APR_SUCCESS) {
270 return rv;
273 *len = total;
274 return APR_SUCCESS;
277 APU_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut,
278 apr_bucket_brigade *bbIn,
279 apr_read_type_e block,
280 apr_off_t maxbytes)
282 apr_off_t readbytes = 0;
284 while (!APR_BRIGADE_EMPTY(bbIn)) {
285 const char *pos;
286 const char *str;
287 apr_size_t len;
288 apr_status_t rv;
289 apr_bucket *e;
291 e = APR_BRIGADE_FIRST(bbIn);
292 rv = apr_bucket_read(e, &str, &len, block);
294 if (rv != APR_SUCCESS) {
295 return rv;
298 pos = memchr(str, APR_ASCII_LF, len);
299 /* We found a match. */
300 if (pos != NULL) {
301 apr_bucket_split(e, pos - str + 1);
302 APR_BUCKET_REMOVE(e);
303 APR_BRIGADE_INSERT_TAIL(bbOut, e);
304 return APR_SUCCESS;
306 APR_BUCKET_REMOVE(e);
307 APR_BRIGADE_INSERT_TAIL(bbOut, e);
308 readbytes += len;
309 /* We didn't find an APR_ASCII_LF within the maximum line length. */
310 if (readbytes >= maxbytes) {
311 break;
315 return APR_SUCCESS;
319 APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b,
320 struct iovec *vec, int *nvec)
322 int left = *nvec;
323 apr_bucket *e;
324 struct iovec *orig;
325 apr_size_t iov_len;
326 const char *iov_base;
327 apr_status_t rv;
329 orig = vec;
331 for (e = APR_BRIGADE_FIRST(b);
332 e != APR_BRIGADE_SENTINEL(b);
333 e = APR_BUCKET_NEXT(e))
335 if (left-- == 0)
336 break;
338 rv = apr_bucket_read(e, &iov_base, &iov_len, APR_NONBLOCK_READ);
339 if (rv != APR_SUCCESS)
340 return rv;
341 /* Set indirectly since types differ: */
342 vec->iov_len = iov_len;
343 vec->iov_base = (void *)iov_base;
344 ++vec;
347 *nvec = vec - orig;
348 return APR_SUCCESS;
351 APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b,
352 apr_brigade_flush flush,
353 void *ctx,
354 va_list va)
356 for (;;) {
357 const char *str = va_arg(va, const char *);
358 apr_status_t rv;
360 if (str == NULL)
361 break;
363 rv = apr_brigade_write(b, flush, ctx, str, strlen(str));
364 if (rv != APR_SUCCESS)
365 return rv;
368 return APR_SUCCESS;
371 APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
372 apr_brigade_flush flush, void *ctx,
373 const char c)
375 return apr_brigade_write(b, flush, ctx, &c, 1);
378 APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
379 apr_brigade_flush flush,
380 void *ctx,
381 const char *str, apr_size_t nbyte)
383 apr_bucket *e = APR_BRIGADE_LAST(b);
384 apr_size_t remaining = APR_BUCKET_BUFF_SIZE;
385 char *buf = NULL;
387 if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
388 apr_bucket_heap *h = e->data;
390 /* HEAP bucket start offsets are always in-memory, safe to cast */
391 remaining = h->alloc_len - (e->length + (apr_size_t)e->start);
392 buf = h->base + e->start + e->length;
395 if (nbyte > remaining) {
396 /* either a buffer bucket exists but is full,
397 * or no buffer bucket exists and the data is too big
398 * to buffer. In either case, we should flush. */
399 if (flush) {
400 e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc);
401 APR_BRIGADE_INSERT_TAIL(b, e);
402 return flush(b, ctx);
404 else {
405 e = apr_bucket_heap_create(str, nbyte, NULL, b->bucket_alloc);
406 APR_BRIGADE_INSERT_TAIL(b, e);
407 return APR_SUCCESS;
410 else if (!buf) {
411 /* we don't have a buffer, but the data is small enough
412 * that we don't mind making a new buffer */
413 buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
414 e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
415 apr_bucket_free, b->bucket_alloc);
416 APR_BRIGADE_INSERT_TAIL(b, e);
417 e->length = 0; /* We are writing into the brigade, and
418 * allocating more memory than we need. This
419 * ensures that the bucket thinks it is empty just
420 * after we create it. We'll fix the length
421 * once we put data in it below.
425 /* there is a sufficiently big buffer bucket available now */
426 memcpy(buf, str, nbyte);
427 e->length += nbyte;
429 return APR_SUCCESS;
432 APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
433 apr_brigade_flush flush,
434 void *ctx,
435 const struct iovec *vec,
436 apr_size_t nvec)
438 apr_bucket *e;
439 apr_size_t total_len;
440 apr_size_t i;
441 char *buf;
443 /* Compute the total length of the data to be written.
445 total_len = 0;
446 for (i = 0; i < nvec; i++) {
447 total_len += vec[i].iov_len;
450 /* If the data to be written is very large, try to convert
451 * the iovec to transient buckets rather than copying.
453 if (total_len > APR_BUCKET_BUFF_SIZE) {
454 if (flush) {
455 for (i = 0; i < nvec; i++) {
456 e = apr_bucket_transient_create(vec[i].iov_base,
457 vec[i].iov_len,
458 b->bucket_alloc);
459 APR_BRIGADE_INSERT_TAIL(b, e);
461 return flush(b, ctx);
463 else {
464 for (i = 0; i < nvec; i++) {
465 e = apr_bucket_heap_create((const char *) vec[i].iov_base,
466 vec[i].iov_len, NULL,
467 b->bucket_alloc);
468 APR_BRIGADE_INSERT_TAIL(b, e);
470 return APR_SUCCESS;
474 i = 0;
476 /* If there is a heap bucket at the end of the brigade
477 * already, copy into the existing bucket.
479 e = APR_BRIGADE_LAST(b);
480 if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
481 apr_bucket_heap *h = e->data;
482 apr_size_t remaining = h->alloc_len -
483 (e->length + (apr_size_t)e->start);
484 buf = h->base + e->start + e->length;
486 if (remaining >= total_len) {
487 /* Simple case: all the data will fit in the
488 * existing heap bucket
490 for (; i < nvec; i++) {
491 apr_size_t len = vec[i].iov_len;
492 memcpy(buf, (const void *) vec[i].iov_base, len);
493 buf += len;
495 e->length += total_len;
496 return APR_SUCCESS;
498 else {
499 /* More complicated case: not all of the data
500 * will fit in the existing heap bucket. The
501 * total data size is <= APR_BUCKET_BUFF_SIZE,
502 * so we'll need only one additional bucket.
504 const char *start_buf = buf;
505 for (; i < nvec; i++) {
506 apr_size_t len = vec[i].iov_len;
507 if (len > remaining) {
508 break;
510 memcpy(buf, (const void *) vec[i].iov_base, len);
511 buf += len;
512 remaining -= len;
514 e->length += (buf - start_buf);
515 total_len -= (buf - start_buf);
517 if (flush) {
518 apr_status_t rv = flush(b, ctx);
519 if (rv != APR_SUCCESS) {
520 return rv;
524 /* Now fall through into the case below to
525 * allocate another heap bucket and copy the
526 * rest of the array. (Note that i is not
527 * reset to zero here; it holds the index
528 * of the first vector element to be
529 * written to the new bucket.)
534 /* Allocate a new heap bucket, and copy the data into it.
535 * The checks above ensure that the amount of data to be
536 * written here is no larger than APR_BUCKET_BUFF_SIZE.
538 buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
539 e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
540 apr_bucket_free, b->bucket_alloc);
541 for (; i < nvec; i++) {
542 apr_size_t len = vec[i].iov_len;
543 memcpy(buf, (const void *) vec[i].iov_base, len);
544 buf += len;
546 e->length = total_len;
547 APR_BRIGADE_INSERT_TAIL(b, e);
549 return APR_SUCCESS;
552 APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
553 apr_brigade_flush flush, void *ctx,
554 const char *str)
556 apr_size_t len = strlen(str);
557 apr_bucket *bkt = APR_BRIGADE_LAST(bb);
558 if (!APR_BRIGADE_EMPTY(bb) && APR_BUCKET_IS_HEAP(bkt)) {
559 /* If there is enough space available in a heap bucket
560 * at the end of the brigade, copy the string directly
561 * into the heap bucket
563 apr_bucket_heap *h = bkt->data;
564 apr_size_t bytes_avail = h->alloc_len - bkt->length;
566 if (bytes_avail >= len) {
567 char *buf = h->base + bkt->start + bkt->length;
568 memcpy(buf, str, len);
569 bkt->length += len;
570 return APR_SUCCESS;
574 /* If the string could not be copied into an existing heap
575 * bucket, delegate the work to apr_brigade_write(), which
576 * knows how to grow the brigade
578 return apr_brigade_write(bb, flush, ctx, str, len);
581 APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b,
582 apr_brigade_flush flush,
583 void *ctx, ...)
585 va_list va;
586 apr_status_t rv;
588 va_start(va, ctx);
589 rv = apr_brigade_vputstrs(b, flush, ctx, va);
590 va_end(va);
591 return rv;
594 APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b,
595 apr_brigade_flush flush,
596 void *ctx,
597 const char *fmt, ...)
599 va_list ap;
600 apr_status_t rv;
602 va_start(ap, fmt);
603 rv = apr_brigade_vprintf(b, flush, ctx, fmt, ap);
604 va_end(ap);
605 return rv;
608 struct brigade_vprintf_data_t {
609 apr_vformatter_buff_t vbuff;
611 apr_bucket_brigade *b; /* associated brigade */
612 apr_brigade_flush *flusher; /* flushing function */
613 void *ctx;
615 char *cbuff; /* buffer to flush from */
618 static apr_status_t brigade_flush(apr_vformatter_buff_t *buff)
620 /* callback function passed to ap_vformatter to be
621 * called when vformatter needs to buff and
622 * buff.curpos > buff.endpos
625 /* "downcast," have really passed a brigade_vprintf_data_t* */
626 struct brigade_vprintf_data_t *vd = (struct brigade_vprintf_data_t*)buff;
627 apr_status_t res = APR_SUCCESS;
629 res = apr_brigade_write(vd->b, *vd->flusher, vd->ctx, vd->cbuff,
630 APR_BUCKET_BUFF_SIZE);
632 if(res != APR_SUCCESS) {
633 return -1;
636 vd->vbuff.curpos = vd->cbuff;
637 vd->vbuff.endpos = vd->cbuff + APR_BUCKET_BUFF_SIZE;
639 return res;
642 APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b,
643 apr_brigade_flush flush,
644 void *ctx,
645 const char *fmt, va_list va)
647 /* the cast, in order of appearance */
648 struct brigade_vprintf_data_t vd;
649 char buf[APR_BUCKET_BUFF_SIZE];
650 apr_size_t written;
652 vd.vbuff.curpos = buf;
653 vd.vbuff.endpos = buf + APR_BUCKET_BUFF_SIZE;
654 vd.b = b;
655 vd.flusher = &flush;
656 vd.ctx = ctx;
657 vd.cbuff = buf;
659 written = apr_vformatter(brigade_flush, &vd.vbuff, fmt, va);
661 if (written == -1) {
662 return -1;
665 /* tack on null terminator to remaining string */
666 *(vd.vbuff.curpos) = '\0';
668 /* write out what remains in the buffer */
669 return apr_brigade_write(b, flush, ctx, buf, vd.vbuff.curpos - buf);
672 /* A "safe" maximum bucket size, 1Gb */
673 #define MAX_BUCKET_SIZE (0x40000000)
675 APU_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb,
676 apr_file_t *f,
677 apr_off_t start,
678 apr_off_t length,
679 apr_pool_t *p)
681 apr_bucket *e;
683 if (sizeof(apr_off_t) == sizeof(apr_size_t) || length < MAX_BUCKET_SIZE) {
684 e = apr_bucket_file_create(f, start, (apr_size_t)length, p,
685 bb->bucket_alloc);
687 else {
688 /* Several buckets are needed. */
689 e = apr_bucket_file_create(f, start, MAX_BUCKET_SIZE, p,
690 bb->bucket_alloc);
692 while (length > MAX_BUCKET_SIZE) {
693 apr_bucket *ce;
694 apr_bucket_copy(e, &ce);
695 APR_BRIGADE_INSERT_TAIL(bb, ce);
696 e->start += MAX_BUCKET_SIZE;
697 length -= MAX_BUCKET_SIZE;
699 e->length = (apr_size_t)length; /* Resize just the last bucket */
702 APR_BRIGADE_INSERT_TAIL(bb, e);
703 return e;