summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2021-09-19 17:07:33 +0000
committerylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2021-09-19 17:07:33 +0000
commit8d6dbf7e48b5015106652a6c5ebba610a91e4b85 (patch)
tree60d5e363a7dd9828168bec3cdabdc76040bff972
parentd230af71c516bc946d582d1a38c164e696319e16 (diff)
downloadlibapr-util-8d6dbf7e48b5015106652a6c5ebba610a91e4b85.tar.gz
Partially merge r1893204, r1893445 from trunk:
apr_file_setasidea() needs to invalidate the old file descriptor per semantics: * @remark After calling this function, old_file may not be used So to avoid the setaside issue with splitted file buckets, file_bucket_setaside() will now apr_file_dup() instead of apr_file_setaside() when the bucket is shared (i.e. refcount > 1). Submitted by: ylavic git-svn-id: https://svn.apache.org/repos/asf/apr/apr-util/branches/1.6.x@1893448 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--buckets/apr_buckets_file.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/buckets/apr_buckets_file.c b/buckets/apr_buckets_file.c
index 06b7cf00..a6f03cc6 100644
--- a/buckets/apr_buckets_file.c
+++ b/buckets/apr_buckets_file.c
@@ -212,9 +212,9 @@ APU_DECLARE(apr_status_t) apr_bucket_file_set_buf_size(apr_bucket *e,
return APR_SUCCESS;
}
-static apr_status_t file_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool)
+static apr_status_t file_bucket_setaside(apr_bucket *b, apr_pool_t *reqpool)
{
- apr_bucket_file *a = data->data;
+ apr_bucket_file *a = b->data;
apr_file_t *fd = NULL;
apr_file_t *f = a->fd;
apr_pool_t *curpool = apr_file_pool_get(f);
@@ -223,11 +223,33 @@ static apr_status_t file_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool)
return APR_SUCCESS;
}
- if (!apr_pool_is_ancestor(a->readpool, reqpool)) {
- a->readpool = reqpool;
- }
+ /* If the file is shared/split accross multiple buckets, this bucket can't
+ * take exclusive ownership with apr_file_setaside() (thus invalidating the
+ * f->filedes), let's apr_file_dup() in this case instead.
+ */
+ if (a->refcount.refcount > 1) {
+ apr_bucket_file *new;
+ apr_status_t rv;
+
+ rv = apr_file_dup(&fd, f, reqpool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
- apr_file_setaside(&fd, f, reqpool);
+ new = apr_bucket_alloc(sizeof(*new), b->list);
+ memcpy(new, a, sizeof(*new));
+ new->refcount.refcount = 1;
+ new->readpool = reqpool;
+
+ a->refcount.refcount--;
+ a = b->data = new;
+ }
+ else {
+ apr_file_setaside(&fd, f, reqpool);
+ if (!apr_pool_is_ancestor(a->readpool, reqpool)) {
+ a->readpool = reqpool;
+ }
+ }
a->fd = fd;
return APR_SUCCESS;
}