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.
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
)
326 const char *iov_base
;
331 for (e
= APR_BRIGADE_FIRST(b
);
332 e
!= APR_BRIGADE_SENTINEL(b
);
333 e
= APR_BUCKET_NEXT(e
))
338 rv
= apr_bucket_read(e
, &iov_base
, &iov_len
, APR_NONBLOCK_READ
);
339 if (rv
!= APR_SUCCESS
)
341 /* Set indirectly since types differ: */
342 vec
->iov_len
= iov_len
;
343 vec
->iov_base
= (void *)iov_base
;
351 APU_DECLARE(apr_status_t
) apr_brigade_vputstrs(apr_bucket_brigade
*b
,
352 apr_brigade_flush flush
,
357 const char *str
= va_arg(va
, const char *);
363 rv
= apr_brigade_write(b
, flush
, ctx
, str
, strlen(str
));
364 if (rv
!= APR_SUCCESS
)
371 APU_DECLARE(apr_status_t
) apr_brigade_putc(apr_bucket_brigade
*b
,
372 apr_brigade_flush flush
, void *ctx
,
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
,
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
;
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. */
400 e
= apr_bucket_transient_create(str
, nbyte
, b
->bucket_alloc
);
401 APR_BRIGADE_INSERT_TAIL(b
, e
);
402 return flush(b
, ctx
);
405 e
= apr_bucket_heap_create(str
, nbyte
, NULL
, b
->bucket_alloc
);
406 APR_BRIGADE_INSERT_TAIL(b
, e
);
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
);
432 APU_DECLARE(apr_status_t
) apr_brigade_writev(apr_bucket_brigade
*b
,
433 apr_brigade_flush flush
,
435 const struct iovec
*vec
,
439 apr_size_t total_len
;
443 /* Compute the total length of the data to be written.
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
) {
455 for (i
= 0; i
< nvec
; i
++) {
456 e
= apr_bucket_transient_create(vec
[i
].iov_base
,
459 APR_BRIGADE_INSERT_TAIL(b
, e
);
461 return flush(b
, ctx
);
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
,
468 APR_BRIGADE_INSERT_TAIL(b
, e
);
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
);
495 e
->length
+= total_len
;
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
) {
510 memcpy(buf
, (const void *) vec
[i
].iov_base
, len
);
514 e
->length
+= (buf
- start_buf
);
515 total_len
-= (buf
- start_buf
);
518 apr_status_t rv
= flush(b
, ctx
);
519 if (rv
!= APR_SUCCESS
) {
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
);
546 e
->length
= total_len
;
547 APR_BRIGADE_INSERT_TAIL(b
, e
);
552 APU_DECLARE(apr_status_t
) apr_brigade_puts(apr_bucket_brigade
*bb
,
553 apr_brigade_flush flush
, void *ctx
,
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
);
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
,
589 rv
= apr_brigade_vputstrs(b
, flush
, ctx
, va
);
594 APU_DECLARE_NONSTD(apr_status_t
) apr_brigade_printf(apr_bucket_brigade
*b
,
595 apr_brigade_flush flush
,
597 const char *fmt
, ...)
603 rv
= apr_brigade_vprintf(b
, flush
, ctx
, fmt
, ap
);
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 */
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
) {
636 vd
->vbuff
.curpos
= vd
->cbuff
;
637 vd
->vbuff
.endpos
= vd
->cbuff
+ APR_BUCKET_BUFF_SIZE
;
642 APU_DECLARE(apr_status_t
) apr_brigade_vprintf(apr_bucket_brigade
*b
,
643 apr_brigade_flush flush
,
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
];
652 vd
.vbuff
.curpos
= buf
;
653 vd
.vbuff
.endpos
= buf
+ APR_BUCKET_BUFF_SIZE
;
659 written
= apr_vformatter(brigade_flush
, &vd
.vbuff
, fmt
, va
);
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
,
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
,
688 /* Several buckets are needed. */
689 e
= apr_bucket_file_create(f
, start
, MAX_BUCKET_SIZE
, p
,
692 while (length
> MAX_BUCKET_SIZE
) {
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
);