xref: /aosp_15_r20/external/cronet/third_party/apache-portable-runtime/src/mmap/win32/mmap.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 "apr.h"
18 #include "apr_private.h"
19 #include "apr_general.h"
20 #include "apr_mmap.h"
21 #include "apr_errno.h"
22 #include "apr_arch_file_io.h"
23 #include "apr_portable.h"
24 #include "apr_strings.h"
25 
26 #if APR_HAS_MMAP
27 
mmap_cleanup(void * themmap)28 static apr_status_t mmap_cleanup(void *themmap)
29 {
30     apr_mmap_t *mm = themmap;
31     apr_mmap_t *next = APR_RING_NEXT(mm,link);
32 
33     /* we no longer refer to the mmaped region */
34     APR_RING_REMOVE(mm,link);
35     APR_RING_NEXT(mm,link) = NULL;
36     APR_RING_PREV(mm,link) = NULL;
37 
38     if (next != mm) {
39         /* more references exist, so we're done */
40         return APR_SUCCESS;
41     }
42 
43     if (mm->mv) {
44         if (!UnmapViewOfFile(mm->mv))
45         {
46             apr_status_t rv = apr_get_os_error();
47             CloseHandle(mm->mhandle);
48             mm->mv = NULL;
49             mm->mhandle = NULL;
50             return rv;
51         }
52         mm->mv = NULL;
53     }
54     if (mm->mhandle)
55     {
56         if (!CloseHandle(mm->mhandle))
57         {
58             apr_status_t rv = apr_get_os_error();
59             CloseHandle(mm->mhandle);
60             mm->mhandle = NULL;
61             return rv;
62         }
63         mm->mhandle = NULL;
64     }
65     return APR_SUCCESS;
66 }
67 
apr_mmap_create(apr_mmap_t ** new,apr_file_t * file,apr_off_t offset,apr_size_t size,apr_int32_t flag,apr_pool_t * cont)68 APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, apr_file_t *file,
69                                           apr_off_t offset, apr_size_t size,
70                                           apr_int32_t flag, apr_pool_t *cont)
71 {
72     static DWORD memblock = 0;
73     DWORD fmaccess = 0;
74     DWORD mvaccess = 0;
75     DWORD offlo;
76     DWORD offhi;
77 
78     if (size == 0)
79         return APR_EINVAL;
80 
81     if (flag & APR_MMAP_WRITE)
82         fmaccess |= PAGE_READWRITE;
83     else if (flag & APR_MMAP_READ)
84         fmaccess |= PAGE_READONLY;
85 
86     if (flag & APR_MMAP_READ)
87         mvaccess |= FILE_MAP_READ;
88     if (flag & APR_MMAP_WRITE)
89         mvaccess |= FILE_MAP_WRITE;
90 
91     if (!file || !file->filehand || file->filehand == INVALID_HANDLE_VALUE
92         || file->buffered)
93         return APR_EBADF;
94 
95     if (!memblock)
96     {
97         SYSTEM_INFO si;
98         GetSystemInfo(&si);
99         memblock = si.dwAllocationGranularity;
100     }
101 
102     *new = apr_pcalloc(cont, sizeof(apr_mmap_t));
103     (*new)->pstart = (offset / memblock) * memblock;
104     (*new)->poffset = offset - (*new)->pstart;
105     (*new)->psize = (apr_size_t)((*new)->poffset) + size;
106     /* The size of the CreateFileMapping object is the current size
107      * of the size of the mmap object (e.g. file size), not the size
108      * of the mapped region!
109      */
110 
111     (*new)->mhandle = CreateFileMapping(file->filehand, NULL, fmaccess,
112                                         0, 0, NULL);
113     if (!(*new)->mhandle || (*new)->mhandle == INVALID_HANDLE_VALUE)
114     {
115         *new = NULL;
116         return apr_get_os_error();
117     }
118 
119     offlo = (DWORD)(*new)->pstart;
120     offhi = (DWORD)((*new)->pstart >> 32);
121     (*new)->mv = MapViewOfFile((*new)->mhandle, mvaccess, offhi,
122                                offlo, (*new)->psize);
123     if (!(*new)->mv)
124     {
125         apr_status_t rv = apr_get_os_error();
126         CloseHandle((*new)->mhandle);
127         *new = NULL;
128         return rv;
129     }
130 
131     (*new)->mm = (char*)((*new)->mv) + (*new)->poffset;
132     (*new)->size = size;
133     (*new)->cntxt = cont;
134     APR_RING_ELEM_INIT(*new, link);
135 
136     /* register the cleanup... */
137     apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup,
138                          apr_pool_cleanup_null);
139     return APR_SUCCESS;
140 }
141 
apr_mmap_dup(apr_mmap_t ** new_mmap,apr_mmap_t * old_mmap,apr_pool_t * p)142 APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap,
143                                        apr_mmap_t *old_mmap,
144                                        apr_pool_t *p)
145 {
146     *new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t));
147     (*new_mmap)->cntxt = p;
148 
149     APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link);
150 
151     apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup,
152                               apr_pool_cleanup_null);
153     return APR_SUCCESS;
154 }
155 
apr_mmap_delete(apr_mmap_t * mm)156 APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm)
157 {
158     return apr_pool_cleanup_run(mm->cntxt, mm, mmap_cleanup);
159 }
160 
161 #endif
162