1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* 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.
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
28
#if APR_HAVE_SYS_UIO_H
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;
42
while (!APR_BRIGADE_EMPTY(b)) {
43
e = APR_BRIGADE_FIRST(b);
46
/* We don't need to free(bb) because it's allocated from a pool. */
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));
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);
71
APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
74
apr_bucket_brigade *a;
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);
93
APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
95
apr_bucket **after_point)
103
/* this could cause weird (not necessarily SEGV) things to happen */
107
*after_point = APR_BRIGADE_FIRST(b);
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) {
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))
132
*after_point = APR_BUCKET_NEXT(e);
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) {
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);
153
if (point == e->length) {
154
*after_point = APR_BUCKET_NEXT(e);
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)
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)) {
183
if ((status = apr_bucket_read(bkt, &ignore, &len,
184
APR_BLOCK_READ)) != APR_SUCCESS) {
189
total += bkt->length;
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;
202
for (b = APR_BRIGADE_FIRST(bb);
203
b != APR_BRIGADE_SENTINEL(bb);
204
b = APR_BUCKET_NEXT(b))
210
status = apr_bucket_read(b, &str, &str_len, APR_BLOCK_READ);
211
if (status != APR_SUCCESS) {
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);
230
/* This could probably be actual == *len, but be safe from stray
232
if (actual >= *len) {
241
APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb,
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) {
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,
282
apr_off_t readbytes = 0;
284
while (!APR_BRIGADE_EMPTY(bbIn)) {
291
e = APR_BRIGADE_FIRST(bbIn);
292
rv = apr_bucket_read(e, &str, &len, block);
294
if (rv != APR_SUCCESS) {
298
pos = memchr(str, APR_ASCII_LF, len);
299
/* We found a match. */
301
apr_bucket_split(e, pos - str + 1);
302
APR_BUCKET_REMOVE(e);
303
APR_BRIGADE_INSERT_TAIL(bbOut, e);
306
APR_BUCKET_REMOVE(e);
307
APR_BRIGADE_INSERT_TAIL(bbOut, e);
309
/* We didn't find an APR_ASCII_LF within the maximum line length. */
310
if (readbytes >= maxbytes) {
319
APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b,
320
struct iovec *vec, int *nvec)
330
for (e = APR_BRIGADE_FIRST(b);
331
e != APR_BRIGADE_SENTINEL(b);
332
e = APR_BUCKET_NEXT(e))
337
rv = apr_bucket_read(e, (const char **)&vec->iov_base, &iov_len,
339
if (rv != APR_SUCCESS)
341
vec->iov_len = iov_len; /* set indirectly in case size differs */
349
APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b,
350
apr_brigade_flush flush,
355
const char *str = va_arg(va, const char *);
361
rv = apr_brigade_write(b, flush, ctx, str, strlen(str));
362
if (rv != APR_SUCCESS)
369
APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
370
apr_brigade_flush flush, void *ctx,
373
return apr_brigade_write(b, flush, ctx, &c, 1);
376
APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
377
apr_brigade_flush flush,
379
const char *str, apr_size_t nbyte)
381
apr_bucket *e = APR_BRIGADE_LAST(b);
382
apr_size_t remaining = APR_BUCKET_BUFF_SIZE;
385
if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
386
apr_bucket_heap *h = e->data;
388
/* HEAP bucket start offsets are always in-memory, safe to cast */
389
remaining = h->alloc_len - (e->length + (apr_size_t)e->start);
390
buf = h->base + e->start + e->length;
393
if (nbyte > remaining) {
394
/* either a buffer bucket exists but is full,
395
* or no buffer bucket exists and the data is too big
396
* to buffer. In either case, we should flush. */
398
e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc);
399
APR_BRIGADE_INSERT_TAIL(b, e);
400
return flush(b, ctx);
403
e = apr_bucket_heap_create(str, nbyte, NULL, b->bucket_alloc);
404
APR_BRIGADE_INSERT_TAIL(b, e);
409
/* we don't have a buffer, but the data is small enough
410
* that we don't mind making a new buffer */
411
buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
412
e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
413
apr_bucket_free, b->bucket_alloc);
414
APR_BRIGADE_INSERT_TAIL(b, e);
415
e->length = 0; /* We are writing into the brigade, and
416
* allocating more memory than we need. This
417
* ensures that the bucket thinks it is empty just
418
* after we create it. We'll fix the length
419
* once we put data in it below.
423
/* there is a sufficiently big buffer bucket available now */
424
memcpy(buf, str, nbyte);
430
APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
431
apr_brigade_flush flush,
433
const struct iovec *vec,
437
apr_size_t total_len;
441
/* Compute the total length of the data to be written.
444
for (i = 0; i < nvec; i++) {
445
total_len += vec[i].iov_len;
448
/* If the data to be written is very large, try to convert
449
* the iovec to transient buckets rather than copying.
451
if (total_len > APR_BUCKET_BUFF_SIZE) {
453
for (i = 0; i < nvec; i++) {
454
e = apr_bucket_transient_create(vec[i].iov_base,
457
APR_BRIGADE_INSERT_TAIL(b, e);
459
return flush(b, ctx);
462
for (i = 0; i < nvec; i++) {
463
e = apr_bucket_heap_create((const char *) vec[i].iov_base,
464
vec[i].iov_len, NULL,
466
APR_BRIGADE_INSERT_TAIL(b, e);
474
/* If there is a heap bucket at the end of the brigade
475
* already, copy into the existing bucket.
477
e = APR_BRIGADE_LAST(b);
478
if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
479
apr_bucket_heap *h = e->data;
480
apr_size_t remaining = h->alloc_len -
481
(e->length + (apr_size_t)e->start);
482
buf = h->base + e->start + e->length;
484
if (remaining >= total_len) {
485
/* Simple case: all the data will fit in the
486
* existing heap bucket
488
for (; i < nvec; i++) {
489
apr_size_t len = vec[i].iov_len;
490
memcpy(buf, (const void *) vec[i].iov_base, len);
493
e->length += total_len;
497
/* More complicated case: not all of the data
498
* will fit in the existing heap bucket. The
499
* total data size is <= APR_BUCKET_BUFF_SIZE,
500
* so we'll need only one additional bucket.
502
const char *start_buf = buf;
503
for (; i < nvec; i++) {
504
apr_size_t len = vec[i].iov_len;
505
if (len > remaining) {
508
memcpy(buf, (const void *) vec[i].iov_base, len);
512
e->length += (buf - start_buf);
513
total_len -= (buf - start_buf);
516
apr_status_t rv = flush(b, ctx);
517
if (rv != APR_SUCCESS) {
522
/* Now fall through into the case below to
523
* allocate another heap bucket and copy the
524
* rest of the array. (Note that i is not
525
* reset to zero here; it holds the index
526
* of the first vector element to be
527
* written to the new bucket.)
532
/* Allocate a new heap bucket, and copy the data into it.
533
* The checks above ensure that the amount of data to be
534
* written here is no larger than APR_BUCKET_BUFF_SIZE.
536
buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
537
e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
538
apr_bucket_free, b->bucket_alloc);
539
for (; i < nvec; i++) {
540
apr_size_t len = vec[i].iov_len;
541
memcpy(buf, (const void *) vec[i].iov_base, len);
544
e->length = total_len;
545
APR_BRIGADE_INSERT_TAIL(b, e);
550
APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
551
apr_brigade_flush flush, void *ctx,
554
apr_size_t len = strlen(str);
555
apr_bucket *bkt = APR_BRIGADE_LAST(bb);
556
if (!APR_BRIGADE_EMPTY(bb) && APR_BUCKET_IS_HEAP(bkt)) {
557
/* If there is enough space available in a heap bucket
558
* at the end of the brigade, copy the string directly
559
* into the heap bucket
561
apr_bucket_heap *h = bkt->data;
562
apr_size_t bytes_avail = h->alloc_len - bkt->length;
564
if (bytes_avail >= len) {
565
char *buf = h->base + bkt->start + bkt->length;
566
memcpy(buf, str, len);
572
/* If the string could not be copied into an existing heap
573
* bucket, delegate the work to apr_brigade_write(), which
574
* knows how to grow the brigade
576
return apr_brigade_write(bb, flush, ctx, str, len);
579
APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b,
580
apr_brigade_flush flush,
587
rv = apr_brigade_vputstrs(b, flush, ctx, va);
592
APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b,
593
apr_brigade_flush flush,
595
const char *fmt, ...)
601
rv = apr_brigade_vprintf(b, flush, ctx, fmt, ap);
606
struct brigade_vprintf_data_t {
607
apr_vformatter_buff_t vbuff;
609
apr_bucket_brigade *b; /* associated brigade */
610
apr_brigade_flush *flusher; /* flushing function */
613
char *cbuff; /* buffer to flush from */
616
static apr_status_t brigade_flush(apr_vformatter_buff_t *buff)
618
/* callback function passed to ap_vformatter to be
619
* called when vformatter needs to buff and
620
* buff.curpos > buff.endpos
623
/* "downcast," have really passed a brigade_vprintf_data_t* */
624
struct brigade_vprintf_data_t *vd = (struct brigade_vprintf_data_t*)buff;
625
apr_status_t res = APR_SUCCESS;
627
res = apr_brigade_write(vd->b, *vd->flusher, vd->ctx, vd->cbuff,
628
APR_BUCKET_BUFF_SIZE);
630
if(res != APR_SUCCESS) {
634
vd->vbuff.curpos = vd->cbuff;
635
vd->vbuff.endpos = vd->cbuff + APR_BUCKET_BUFF_SIZE;
640
APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b,
641
apr_brigade_flush flush,
643
const char *fmt, va_list va)
645
/* the cast, in order of appearance */
646
struct brigade_vprintf_data_t vd;
647
char buf[APR_BUCKET_BUFF_SIZE];
650
vd.vbuff.curpos = buf;
651
vd.vbuff.endpos = buf + APR_BUCKET_BUFF_SIZE;
657
written = apr_vformatter(brigade_flush, &vd.vbuff, fmt, va);
663
/* tack on null terminator to remaining string */
664
*(vd.vbuff.curpos) = '\0';
666
/* write out what remains in the buffer */
667
return apr_brigade_write(b, flush, ctx, buf, vd.vbuff.curpos - buf);
670
/* A "safe" maximum bucket size, 1Gb */
671
#define MAX_BUCKET_SIZE (0x40000000)
673
APU_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb,
681
if (sizeof(apr_off_t) == sizeof(apr_size_t) || length < MAX_BUCKET_SIZE) {
682
e = apr_bucket_file_create(f, start, (apr_size_t)length, p,
686
/* Several buckets are needed. */
687
e = apr_bucket_file_create(f, start, MAX_BUCKET_SIZE, p,
690
while (length > MAX_BUCKET_SIZE) {
692
apr_bucket_copy(e, &ce);
693
APR_BRIGADE_INSERT_TAIL(bb, ce);
694
e->start += MAX_BUCKET_SIZE;
695
length -= MAX_BUCKET_SIZE;
697
e->length = (apr_size_t)length; /* Resize just the last bucket */
700
APR_BRIGADE_INSERT_TAIL(bb, e);