| 195 | } |
| 196 | |
| 197 | static apr_status_t read_to_scratch(h2_c1_io *io, apr_bucket *b) |
| 198 | { |
| 199 | apr_status_t status; |
| 200 | const char *data; |
| 201 | apr_size_t len; |
| 202 | |
| 203 | if (!b->length) { |
| 204 | return APR_SUCCESS; |
| 205 | } |
| 206 | |
| 207 | ap_assert(b->length <= (io->ssize - io->slen)); |
| 208 | if (APR_BUCKET_IS_FILE(b)) { |
| 209 | apr_bucket_file *f = (apr_bucket_file *)b->data; |
| 210 | apr_file_t *fd = f->fd; |
| 211 | apr_off_t offset = b->start; |
| 212 | |
| 213 | len = b->length; |
| 214 | /* file buckets will read 8000 byte chunks and split |
| 215 | * themselves. However, we do know *exactly* how many |
| 216 | * bytes we need where. So we read the file directly to |
| 217 | * where we need it. |
| 218 | */ |
| 219 | status = apr_file_seek(fd, APR_SET, &offset); |
| 220 | if (status != APR_SUCCESS) { |
| 221 | return status; |
| 222 | } |
| 223 | status = apr_file_read(fd, io->scratch + io->slen, &len); |
| 224 | if (status != APR_SUCCESS && status != APR_EOF) { |
| 225 | return status; |
| 226 | } |
| 227 | io->slen += len; |
| 228 | } |
| 229 | else if (APR_BUCKET_IS_MMAP(b)) { |
| 230 | ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, io->session->c1, |
| 231 | "h2_c1_io(%ld): seeing mmap bucket of size %ld, scratch remain=%ld", |
| 232 | io->session->c1->id, (long)b->length, (long)(io->ssize - io->slen)); |
| 233 | status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ); |
| 234 | if (status == APR_SUCCESS) { |
| 235 | memcpy(io->scratch+io->slen, data, len); |
| 236 | io->slen += len; |
| 237 | } |
| 238 | } |
| 239 | else { |
| 240 | status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ); |
| 241 | if (status == APR_SUCCESS) { |
| 242 | memcpy(io->scratch+io->slen, data, len); |
| 243 | io->slen += len; |
| 244 | } |
| 245 | } |
| 246 | return status; |
| 247 | } |
| 248 | |
| 249 | static apr_status_t pass_output(h2_c1_io *io, int flush) |
| 250 | { |