Coverage Report

Created: 2026-09-06 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/httpd/srclib/apr/mmap/unix/mmap.c
Line
Count
Source
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
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
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.
15
 */
16
17
#include <assert.h>
18
19
#include "apr.h"
20
#include "apr_private.h"
21
#include "apr_general.h"
22
#include "apr_strings.h"
23
#include "apr_mmap.h"
24
#include "apr_errno.h"
25
#include "apr_arch_file_io.h"
26
#include "apr_portable.h"
27
28
/* System headers required for the mmap library */
29
#if APR_HAVE_STRING_H
30
#include <string.h>
31
#endif
32
#if APR_HAVE_STDIO_H
33
#include <stdio.h>
34
#endif
35
#if APR_HAVE_UNISTD_H
36
#include <unistd.h>  /* for sysconf() */
37
#endif
38
#ifdef HAVE_SYS_STAT_H
39
#include <sys/stat.h>
40
#endif
41
#ifdef HAVE_SYS_MMAN_H
42
#include <sys/mman.h>
43
#endif
44
45
#if APR_HAS_MMAP
46
47
static apr_status_t mmap_cleanup(void *themmap)
48
0
{
49
0
    apr_mmap_t *mm = themmap;
50
0
    apr_mmap_t *next = APR_RING_NEXT(mm,link);
51
0
    int rv = 0;
52
53
    /* we no longer refer to the mmaped region */
54
0
    APR_RING_REMOVE(mm,link);
55
0
    APR_RING_NEXT(mm,link) = NULL;
56
0
    APR_RING_PREV(mm,link) = NULL;
57
58
0
    if (next != mm) {
59
        /* more references exist, so we're done */
60
0
        return APR_SUCCESS;
61
0
    }
62
63
0
    rv = munmap((char *)mm->mm - mm->poffset, mm->size + mm->poffset);
64
0
    mm->mm = (void *)-1;
65
66
0
    if (rv == 0) {
67
0
        return APR_SUCCESS;
68
0
    }
69
0
    return errno;
70
0
}
71
72
APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new,
73
                                          apr_file_t *file, apr_off_t offset,
74
                                          apr_size_t size, apr_int32_t flag,
75
                                          apr_pool_t *cont)
76
0
{
77
0
    void *mm;
78
0
    static long psize;
79
0
    apr_off_t poffset = 0;
80
0
    apr_int32_t native_flags = 0;
81
82
#if APR_HAS_LARGE_FILES && defined(HAVE_MMAP64)
83
#define mmap mmap64
84
#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4
85
    /* LFS but no mmap64: check for overflow */
86
    if ((apr_int64_t)offset + size > INT_MAX)
87
        return APR_EINVAL;
88
#endif
89
90
0
    if (size == 0)
91
0
        return APR_EINVAL;
92
93
0
    if (file == NULL || file->filedes == -1 || file->buffered)
94
0
        return APR_EBADF;
95
0
    (*new) = (apr_mmap_t *)apr_pcalloc(cont, sizeof(apr_mmap_t));
96
97
0
    if (flag & APR_MMAP_WRITE) {
98
0
        native_flags |= PROT_WRITE;
99
0
    }
100
0
    if (flag & APR_MMAP_READ) {
101
0
        native_flags |= PROT_READ;
102
0
    }
103
104
0
#if defined(_SC_PAGESIZE)
105
0
    if (psize == 0) {
106
0
        psize = sysconf(_SC_PAGESIZE);
107
        /* the page size should be a power of two */
108
0
        assert(psize > 0 && (psize & (psize - 1)) == 0);
109
0
    }
110
0
    poffset = offset & (apr_off_t)(psize - 1);
111
0
    (*new)->poffset = poffset;
112
0
#endif
113
114
0
    mm = mmap(NULL, size + poffset,
115
0
              native_flags, MAP_SHARED,
116
0
              file->filedes, offset - poffset);
117
118
0
    if (mm == (void *)-1) {
119
        /* we failed to get an mmap'd file... */
120
0
        *new = NULL;
121
0
        return errno;
122
0
    }
123
124
0
    mm = (char *)mm + poffset;
125
126
0
    (*new)->mm = mm;
127
0
    (*new)->size = size;
128
0
    (*new)->cntxt = cont;
129
0
    APR_RING_ELEM_INIT(*new, link);
130
131
    /* register the cleanup... */
132
0
    apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup,
133
0
             apr_pool_cleanup_null);
134
0
    return APR_SUCCESS;
135
0
}
136
137
APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
138
                                       apr_mmap_t *old_mmap,
139
                                       apr_pool_t *p)
140
0
{
141
0
    *new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t));
142
0
    (*new_mmap)->cntxt = p;
143
144
0
    APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link);
145
146
0
    apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
147
0
                              apr_pool_cleanup_null);
148
0
    return APR_SUCCESS;
149
0
}
150
151
APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm)
152
0
{
153
0
    return apr_pool_cleanup_run(mm->cntxt, mm, mmap_cleanup);
154
0
}
155
156
#endif