GCC Code Coverage Report


Directory: src/gate/
File: src/gate/io/ipcsharedmem.c
Date: 2026-02-03 22:06:38
Exec Total Coverage
Lines: 55 71 77.5%
Functions: 5 5 100.0%
Branches: 13 24 54.2%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/io/ipcsharedmem.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32
33 #if defined(GATE_SYS_WIN16)
34 # define GATE_IO_SHAREDMEM_NO_IMPL 1
35 #elif defined(GATE_SYS_WIN)
36 # define GATE_IO_SHAREDMEM_WINAPI 1
37 #elif defined(GATE_SYS_ANDROID) || defined(GATE_SYS_BEOS)
38 # define GATE_IO_SHAREDMEM_NO_IMPL 1
39 #elif defined(GATE_SYS_POSIX)
40 # define GATE_IO_SHAREDMEM_POSIX 1
41 #else
42 # define GATE_IO_SHAREDMEM_NO_IMPL 1
43 #endif
44
45
46 typedef struct gate_ipcsharedmem_data_class
47 {
48 gate_uint32_t version;
49 gate_enumint_t flags;
50 gate_uint64_t mem_size;
51 void* data;
52 } gate_ipcsharedmem_data_t;
53
54 #define GATE_IO_SHAREDMEM_VERSION_1 1
55
56
57
58 #if defined(GATE_IO_SHAREDMEM_WINAPI)
59
60 #include "gate/platforms.h"
61
62 static gate_size_t gate_ipcsharedmem_create_uid(HANDLE handle, char* buffer, gate_size_t buffer_len)
63 {
64 gate_size_t ret = 0;
65 gate_strbuilder_t builder = GATE_INIT_EMPTY;
66 DWORD current_process_id = GetCurrentProcessId();
67 gate_uint64_t handle_uid = (gate_uint64_t)(gate_uintptr_t)handle;
68
69 gate_strbuilder_create_static(&builder, buffer, buffer_len, 0);
70
71 ret += gate_strbuilder_append_uint32(&builder, (gate_uint32_t)current_process_id);
72 ret += gate_strbuilder_append_chars(&builder, 1, '~');
73 ret += gate_strbuilder_append_uint64(&builder, handle_uid);
74 return ret;
75 }
76
77 static gate_result_t gate_ipcsharedmem_parse_uid(gate_string_t const* text, DWORD* ptr_procid, HANDLE* ptr_handle)
78 {
79 gate_result_t ret = GATE_RESULT_FAILED;
80 gate_size_t pos;
81 gate_uint64_t n;
82
83 pos = gate_string_char_pos(text, '~', 0);
84 if (pos != GATE_STR_NPOS)
85 {
86 n = 0;
87 gate_str_parse_uint64(gate_string_ptr(text, 0), pos, &n);
88 if (ptr_procid)
89 {
90 *ptr_procid = (DWORD)n;
91 }
92
93 n = 0;
94 gate_str_parse_uint64(gate_string_ptr(text, pos + 1), gate_string_length(text) - pos - 1, &n);
95 if (ptr_handle)
96 {
97 *ptr_handle = (HANDLE)(gate_uintptr_t)n;
98 }
99 ret = GATE_RESULT_OK;
100 }
101
102 return ret;
103 }
104
105
106 gate_result_t gate_ipcsharedmem_create(gate_ipcsharedmem_t* ptr_shmem, gate_size_t memsize, gate_enumint_t flags, gate_string_t* out_uid)
107 {
108 gate_result_t ret = GATE_RESULT_FAILED;
109 SECURITY_ATTRIBUTES sec_attrs = GATE_INIT_EMPTY;
110 gate_size_t total_size = sizeof(gate_ipcsharedmem_data_t) + memsize;
111 DWORD sz_low = 0, sz_high = 0;
112 HANDLE handle = NULL;
113 gate_ipcsharedmem_data_t* dataptr = NULL;
114 char uid_buffer[256];
115 gate_size_t uid_buffer_used = 0;
116
117 do
118 {
119 if ((memsize == 0) && (ptr_shmem == NULL))
120 {
121 ret = GATE_RESULT_INVALIDARG;
122 break;
123 }
124
125 sz_high = (DWORD)(((gate_uint64_t)memsize) >> 32);
126 sz_low = (DWORD)(memsize % 0xffffffff);
127
128 sec_attrs.nLength = sizeof(sec_attrs);
129 sec_attrs.lpSecurityDescriptor = NULL;
130 sec_attrs.bInheritHandle = TRUE;
131
132 handle = CreateFileMapping(INVALID_HANDLE_VALUE, &sec_attrs, PAGE_READWRITE, sz_high, sz_low, NULL);
133 if (NULL == handle)
134 {
135 ret = GATE_RESULT_OUTOFRESOURCES;
136 break;
137 }
138
139 dataptr = (gate_ipcsharedmem_data_t*)MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, total_size);
140 if (NULL == dataptr)
141 {
142 ret = GATE_RESULT_OUTOFRESOURCES;
143 break;
144 }
145 gate_mem_clear(dataptr, total_size);
146 dataptr->version = GATE_IO_SHAREDMEM_VERSION_1;
147 dataptr->flags = flags;
148 dataptr->mem_size = memsize;
149
150 UnmapViewOfFile(dataptr);
151
152 if (out_uid)
153 {
154 uid_buffer_used = gate_ipcsharedmem_create_uid(handle, uid_buffer, sizeof(uid_buffer));
155 gate_string_create(out_uid, uid_buffer, uid_buffer_used);
156 }
157
158 *ptr_shmem = handle;
159 handle = NULL;
160
161 ret = GATE_RESULT_OK;
162 } while (0);
163
164 if (NULL != handle)
165 {
166 CloseHandle(handle);
167 }
168
169 return ret;
170 }
171 gate_result_t gate_ipcsharedmem_open(gate_ipcsharedmem_t* ptr_shmem, gate_string_t const* uid, gate_size_t* out_memsize, gate_enumint_t* out_flags)
172 {
173 gate_result_t ret = GATE_RESULT_FAILED;
174 HANDLE target_handle = NULL;
175
176 do
177 {
178 DWORD proc_id = 0;
179 HANDLE hproc = GetCurrentProcess();
180 HANDLE src_handle = NULL;
181 void* ptr_mem;
182 gate_ipcsharedmem_data_t info_data;
183
184 ret = gate_ipcsharedmem_parse_uid(uid, &proc_id, &src_handle);
185 GATE_BREAK_IF_FAILED(ret);
186
187 if (!DuplicateHandle(hproc, src_handle, hproc, &target_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
188 {
189 ret = GATE_RESULT_FAILED;
190 break;
191 }
192 ptr_mem = MapViewOfFile(target_handle, FILE_MAP_READ, 0, 0, sizeof(gate_ipcsharedmem_data_t));
193 if (!ptr_mem)
194 {
195 ret = GATE_RESULT_FAILED;
196 break;
197 }
198 info_data = *((gate_ipcsharedmem_data_t*)ptr_mem);
199 UnmapViewOfFile(ptr_mem);
200
201 if (out_memsize) *out_memsize = (gate_size_t)(info_data.mem_size);
202 if (out_flags) *out_flags = info_data.flags;
203
204 *ptr_shmem = (gate_ipcsharedmem_t)target_handle;
205 target_handle = NULL;
206 ret = GATE_RESULT_OK;
207
208 } while (0);
209
210 if (target_handle != NULL)
211 {
212 CloseHandle(target_handle);
213 }
214
215 return ret;
216 }
217 gate_result_t gate_ipcsharedmem_destroy(gate_ipcsharedmem_t shmem)
218 {
219 gate_result_t ret = GATE_RESULT_OK;
220 if (shmem)
221 {
222 if (!CloseHandle((HANDLE)shmem))
223 {
224 ret = GATE_RESULT_FAILED;
225 }
226 }
227 return ret;
228 }
229 gate_result_t gate_ipcsharedmem_attach(gate_ipcsharedmem_t shmem, void** ptr_dataptr)
230 {
231 HANDLE hmem = (HANDLE)shmem;
232 void* ptr = MapViewOfFile((HANDLE)hmem, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
233 if (!ptr)
234 {
235 return GATE_RESULT_FAILED;
236 }
237 else
238 {
239 gate_ipcsharedmem_data_t* const ptr_data = (gate_ipcsharedmem_data_t*)ptr;
240 if (ptr_dataptr)
241 {
242 void** const ptr_data_member = &ptr_data->data;
243 *ptr_dataptr = (void*)ptr_data_member;
244 }
245 else
246 {
247 UnmapViewOfFile(ptr);
248 }
249 return GATE_RESULT_OK;
250 }
251 }
252 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t shmem, void* dataptr)
253 {
254 static gate_size_t const offset = offsetof(gate_ipcsharedmem_data_t, data);
255 char* root_ptr;
256 gate_ipcsharedmem_data_t* ptr_data;
257
258 GATE_UNUSED_ARG(shmem);
259 if (dataptr == NULL)
260 {
261 return GATE_RESULT_INVALIDARG;
262 }
263
264 root_ptr = ((char*)dataptr) - offset;
265 ptr_data = (gate_ipcsharedmem_data_t*)root_ptr;
266
267 if (!UnmapViewOfFile((void*)ptr_data))
268 {
269 return GATE_RESULT_FAILED;
270 }
271 return GATE_RESULT_OK;
272 }
273
274 #endif /* GATE_IO_SHAREDMEM_WINAPI */
275
276
277
278
279 #if defined(GATE_IO_SHAREDMEM_POSIX)
280
281 #include "gate/platforms.h"
282 #include "gate/utilities.h"
283 #include <sys/shm.h>
284
285 2 gate_result_t gate_ipcsharedmem_create(gate_ipcsharedmem_t* ptr_ipc_mem, gate_size_t memsize, gate_enumint_t flags, gate_string_t* out_uid)
286 {
287 2 gate_result_t ret = GATE_RESULT_FAILED;
288
289 do
290 {
291 2 gate_size_t const total_size = sizeof(gate_ipcsharedmem_data_t) + memsize;
292 gate_ipcsharedmem_data_t* ptr;
293 int err_code;
294 2 int id = shmget(IPC_PRIVATE, total_size, IPC_CREAT | SHM_R | SHM_W);
295
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (id == -1)
297 {
298 err_code = gate_posix_errno(&ret);
299 break;
300 }
301
302 2 ptr = (gate_ipcsharedmem_data_t*)shmat(id, NULL, 0);
303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ptr == ((void*)-1))
304 {
305 err_code = gate_posix_errno(&ret);
306 shmctl(id, IPC_RMID, NULL);
307 break;
308 }
309
310 2 gate_mem_clear(ptr, total_size);
311 2 ptr->version = GATE_IO_SHAREDMEM_VERSION_1;
312 2 ptr->flags = flags;
313 2 ptr->mem_size = memsize;
314
315 2 shmdt((void*)ptr);
316
317
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (out_uid != NULL)
318 {
319
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_util_int_to_string(out_uid, id))
320 {
321 ret = GATE_RESULT_OUTOFMEMORY;
322 shmctl(id, IPC_RMID, NULL);
323 break;
324 }
325 }
326
327 2 *ptr_ipc_mem = (void*)(gate_intptr_t)id;
328 2 ret = GATE_RESULT_OK;
329 } while (0);
330
331 2 return ret;
332 }
333 1 gate_result_t gate_ipcsharedmem_open(gate_ipcsharedmem_t* ptr_ipc_mem, gate_string_t const* uid, gate_size_t* out_memsize, gate_enumint_t* out_flags)
334 {
335 1 gate_result_t ret = GATE_RESULT_FAILED;
336
337 do
338 {
339 gate_int64_t parsed_id;
340 int id;
341 gate_ipcsharedmem_data_t* ptr;
342
343
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_str_parse_int64(uid->str, uid->length, &parsed_id))
344 {
345 ret = GATE_RESULT_INVALIDARG;
346 break;
347 }
348 1 id = (int)parsed_id;
349 1 ptr = shmat(id, NULL, 0);
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (((void*)ptr) == ((void*)-1))
351 {
352 gate_posix_errno(&ret);
353 break;
354 }
355
356
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (out_memsize)
357 {
358 1 *out_memsize = ptr->mem_size;
359 }
360
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (out_flags)
361 {
362 1 *out_flags = ptr->flags;
363 }
364 1 shmdt((void*)ptr);
365
366 1 *ptr_ipc_mem = (void*)(gate_intptr_t)id;
367 1 ret = GATE_RESULT_OK;
368 } while (0);
369
370 1 return ret;
371 }
372 3 gate_result_t gate_ipcsharedmem_destroy(gate_ipcsharedmem_t shmem)
373 {
374 3 gate_result_t ret = GATE_RESULT_FAILED;
375 3 int id = (int)(intptr_t)shmem;
376 do
377 {
378 3 int result = shmctl(id, IPC_RMID, NULL);
379
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if(result == 0)
380 {
381 2 ret = GATE_RESULT_OK;
382 }
383 } while (0);
384
385 3 return ret;
386 }
387 2 gate_result_t gate_ipcsharedmem_attach(gate_ipcsharedmem_t shmem, void** ptr_dataptr)
388 {
389 2 gate_result_t ret = GATE_RESULT_FAILED;
390
391 do
392 {
393 2 int id = (int)(intptr_t)shmem;
394 2 gate_ipcsharedmem_data_t* ptr = (gate_ipcsharedmem_data_t*)shmat(id, NULL, 0);
395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (((void*)ptr) == ((void*)-1))
396 {
397 ret = GATE_RESULT_FAILED;
398 break;
399 }
400
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptr_dataptr)
401 {
402 2 *ptr_dataptr = (void*)(ptr + 1);
403 }
404 2 ret = GATE_RESULT_OK;
405 } while (0);
406 2 return ret;
407 }
408 2 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t handle, void* dataptr)
409 {
410 2 gate_result_t ret = GATE_RESULT_FAILED;
411 do
412 {
413 gate_ipcsharedmem_data_t* ptr;
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (dataptr == NULL)
415 {
416 ret = GATE_RESULT_NULLPOINTER;
417 break;
418 }
419 2 ptr = (gate_ipcsharedmem_data_t*)dataptr;
420 2 --ptr;
421 2 shmdt((void*)ptr);
422 2 ret = GATE_RESULT_OK;
423 } while (0);
424 2 return ret;
425 }
426
427 #endif /* GATE_IO_SHAREDMEM_POSIX */
428
429
430
431
432 #if defined(GATE_IO_SHAREDMEM_NO_IMPL)
433
434 gate_result_t gate_ipcsharedmem_create(gate_ipcsharedmem_t* mem, gate_size_t memsize, gate_enumint_t flags, gate_string_t* out_uid)
435 {
436 (void)mem;
437 (void)memsize;
438 (void)flags;
439 (void)out_uid;
440 return GATE_RESULT_NOTIMPLEMENTED;
441 }
442 gate_result_t gate_ipcsharedmem_open(gate_ipcsharedmem_t* mem, gate_string_t const* uid, gate_size_t* out_memsize, gate_enumint_t* out_flags)
443 {
444 (void)mem;
445 (void)uid;
446 (void)out_memsize;
447 (void)out_flags;
448 return GATE_RESULT_NOTIMPLEMENTED;
449 }
450 gate_result_t gate_ipcsharedmem_destroy(gate_ipcsharedmem_t handle)
451 {
452 (void)handle;
453 return GATE_RESULT_NOTIMPLEMENTED;
454 }
455 gate_result_t gate_ipcsharedmem_attach(gate_ipcsharedmem_t handle, void** ptr_dataptr)
456 {
457 (void)handle;
458 (void)ptr_dataptr;
459 return GATE_RESULT_NOTIMPLEMENTED;
460 }
461 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t handle, void* dataptr)
462 {
463 (void)handle;
464 (void)dataptr;
465 return GATE_RESULT_NOTIMPLEMENTED;
466 }
467
468 #endif /* GATE_IO_SHAREDMEM_NO_IMPL */
469
470