GCC Code Coverage Report


Directory: src/gate/
File: src/gate/io/ipcsharedmem.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 41 71 57.7%
Functions: 4 5 80.0%
Branches: 8 24 33.3%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, 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* ptr_data = (gate_ipcsharedmem_data_t*)ptr;
240 if (ptr_dataptr)
241 {
242 *ptr_dataptr = (void*)&ptr_data->data;
243 }
244 else
245 {
246 UnmapViewOfFile(ptr);
247 }
248 return GATE_RESULT_OK;
249 }
250 }
251 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t shmem, void* dataptr)
252 {
253 static gate_size_t const offset = offsetof(gate_ipcsharedmem_data_t, data);
254 char* root_ptr;
255 gate_ipcsharedmem_data_t* ptr_data;
256
257 GATE_UNUSED_ARG(shmem);
258 if (dataptr == NULL)
259 {
260 return GATE_RESULT_INVALIDARG;
261 }
262
263 root_ptr = ((char*)dataptr) - offset;
264 ptr_data = (gate_ipcsharedmem_data_t*)root_ptr;
265
266 if (!UnmapViewOfFile((void*)ptr_data))
267 {
268 return GATE_RESULT_FAILED;
269 }
270 return GATE_RESULT_OK;
271 }
272
273 #endif /* GATE_IO_SHAREDMEM_WINAPI */
274
275
276
277
278 #if defined(GATE_IO_SHAREDMEM_POSIX)
279
280 #include "gate/platforms.h"
281 #include "gate/utilities.h"
282 #include <sys/shm.h>
283
284 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)
285 {
286 2 gate_result_t ret = GATE_RESULT_FAILED;
287
288 do
289 {
290 2 gate_size_t const total_size = sizeof(gate_ipcsharedmem_data_t) + memsize;
291 gate_ipcsharedmem_data_t* ptr;
292 int err_code;
293 2 int id = shmget(IPC_PRIVATE, total_size, IPC_CREAT | SHM_R | SHM_W);
294
295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (id == -1)
296 {
297 err_code = gate_posix_errno(&ret);
298 break;
299 }
300
301 2 ptr = (gate_ipcsharedmem_data_t*)shmat(id, NULL, 0);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ptr == ((void*)-1))
303 {
304 err_code = gate_posix_errno(&ret);
305 shmctl(id, IPC_RMID, NULL);
306 break;
307 }
308
309 2 gate_mem_clear(ptr, total_size);
310 2 ptr->version = GATE_IO_SHAREDMEM_VERSION_1;
311 2 ptr->flags = flags;
312 2 ptr->mem_size = memsize;
313
314 2 shmdt((void*)ptr);
315
316
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (out_uid != NULL)
317 {
318
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_util_int_to_string(out_uid, id))
319 {
320 ret = GATE_RESULT_OUTOFMEMORY;
321 shmctl(id, IPC_RMID, NULL);
322 break;
323 }
324 }
325
326 2 *ptr_ipc_mem = (void*)(gate_intptr_t)id;
327 2 ret = GATE_RESULT_OK;
328 } while (0);
329
330 2 return ret;
331 }
332 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)
333 {
334 gate_result_t ret = GATE_RESULT_FAILED;
335
336 do
337 {
338 gate_int64_t parsed_id;
339 int id;
340 gate_ipcsharedmem_data_t* ptr;
341
342 if (0 == gate_str_parse_int64(uid->str, uid->length, &parsed_id))
343 {
344 ret = GATE_RESULT_INVALIDARG;
345 break;
346 }
347 id = (int)parsed_id;
348 ptr = shmat(id, NULL, 0);
349 if (((void*)ptr) == ((void*)-1))
350 {
351 gate_posix_errno(&ret);
352 break;
353 }
354
355 if (out_memsize)
356 {
357 *out_memsize = ptr->mem_size;
358 }
359 if (out_flags)
360 {
361 *out_flags = ptr->flags;
362 }
363 shmdt((void*)ptr);
364
365 *ptr_ipc_mem = (void*)(gate_intptr_t)id;
366 ret = GATE_RESULT_OK;
367 } while (0);
368
369 return ret;
370 }
371 2 gate_result_t gate_ipcsharedmem_destroy(gate_ipcsharedmem_t shmem)
372 {
373 2 gate_result_t ret = GATE_RESULT_FAILED;
374 2 int id = (int)(intptr_t)shmem;
375 do
376 {
377 2 int result = shmctl(id, IPC_RMID, NULL);
378
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(result == 0)
379 {
380 2 ret = GATE_RESULT_OK;
381 }
382 } while (0);
383
384 2 return ret;
385 }
386 2 gate_result_t gate_ipcsharedmem_attach(gate_ipcsharedmem_t shmem, void** ptr_dataptr)
387 {
388 2 gate_result_t ret = GATE_RESULT_FAILED;
389
390 do
391 {
392 2 int id = (int)(intptr_t)shmem;
393 2 gate_ipcsharedmem_data_t* ptr = (gate_ipcsharedmem_data_t*)shmat(id, NULL, 0);
394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (((void*)ptr) == ((void*)-1))
395 {
396 ret = GATE_RESULT_FAILED;
397 break;
398 }
399
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptr_dataptr)
400 {
401 2 *ptr_dataptr = (void*)(ptr + 1);
402 }
403 2 ret = GATE_RESULT_OK;
404 } while (0);
405 2 return ret;
406 }
407 2 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t handle, void* dataptr)
408 {
409 2 gate_result_t ret = GATE_RESULT_FAILED;
410 do
411 {
412 gate_ipcsharedmem_data_t* ptr;
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (dataptr == NULL)
414 {
415 ret = GATE_RESULT_NULLPOINTER;
416 break;
417 }
418 2 ptr = (gate_ipcsharedmem_data_t*)dataptr;
419 2 --ptr;
420 2 shmdt((void*)ptr);
421 2 ret = GATE_RESULT_OK;
422 } while (0);
423 2 return ret;
424 }
425
426 #endif /* GATE_IO_SHAREDMEM_POSIX */
427
428
429
430
431 #if defined(GATE_IO_SHAREDMEM_NO_IMPL)
432
433 gate_result_t gate_ipcsharedmem_create(gate_ipcsharedmem_t* mem, gate_size_t memsize, gate_enumint_t flags, gate_string_t* out_uid)
434 {
435 (void)mem;
436 (void)memsize;
437 (void)flags;
438 (void)out_uid;
439 return GATE_RESULT_NOTIMPLEMENTED;
440 }
441 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)
442 {
443 (void)mem;
444 (void)uid;
445 (void)out_memsize;
446 (void)out_flags;
447 return GATE_RESULT_NOTIMPLEMENTED;
448 }
449 gate_result_t gate_ipcsharedmem_destroy(gate_ipcsharedmem_t handle)
450 {
451 (void)handle;
452 return GATE_RESULT_NOTIMPLEMENTED;
453 }
454 gate_result_t gate_ipcsharedmem_attach(gate_ipcsharedmem_t handle, void** ptr_dataptr)
455 {
456 (void)handle;
457 (void)ptr_dataptr;
458 return GATE_RESULT_NOTIMPLEMENTED;
459 }
460 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t handle, void* dataptr)
461 {
462 (void)handle;
463 (void)dataptr;
464 return GATE_RESULT_NOTIMPLEMENTED;
465 }
466
467 #endif /* GATE_IO_SHAREDMEM_NO_IMPL */
468
469