GCC Code Coverage Report


Directory: src/gate/
File: src/gate/io/ipcsharedmem.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 41 71 57.7%
Functions: 4 5 80.0%
Branches: 7 22 31.8%

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
32 #if defined(GATE_SYS_WIN16)
33 # define GATE_IO_SHAREDMEM_NO_IMPL 1
34 #elif defined(GATE_SYS_WIN)
35 # define GATE_IO_SHAREDMEM_WINAPI 1
36 #elif defined(GATE_SYS_ANDROID) || defined(GATE_SYS_BEOS)
37 # define GATE_IO_SHAREDMEM_NO_IMPL 1
38 #elif defined(GATE_SYS_POSIX)
39 # define GATE_IO_SHAREDMEM_POSIX 1
40 #else
41 # define GATE_IO_SHAREDMEM_NO_IMPL 1
42 #endif
43
44
45 typedef struct gate_ipcsharedmem_data_class
46 {
47 gate_uint32_t version;
48 gate_enumint_t flags;
49 gate_uint64_t mem_size;
50 void* data;
51 } gate_ipcsharedmem_data_t;
52
53 #define GATE_IO_SHAREDMEM_VERSION_1 1
54
55
56
57 #if defined(GATE_IO_SHAREDMEM_WINAPI)
58
59 #include "gate/platforms.h"
60
61 static gate_size_t gate_ipcsharedmem_create_uid(HANDLE handle, char* buffer, gate_size_t buffer_len)
62 {
63 gate_size_t ret = 0;
64 gate_strbuilder_t builder = GATE_INIT_EMPTY;
65 DWORD current_process_id = GetCurrentProcessId();
66 gate_uint64_t handle_uid = (gate_uint64_t)(gate_uintptr_t)handle;
67
68 gate_strbuilder_create_static(&builder, buffer, buffer_len, 0);
69
70 ret += gate_strbuilder_append_uint32(&builder, (gate_uint32_t)current_process_id);
71 ret += gate_strbuilder_append_chars(&builder, 1, '~');
72 ret += gate_strbuilder_append_uint64(&builder, handle_uid);
73 return ret;
74 }
75
76 static gate_result_t gate_ipcsharedmem_parse_uid(gate_string_t const* text, DWORD* ptr_procid, HANDLE* ptr_handle)
77 {
78 gate_result_t ret = GATE_RESULT_FAILED;
79 gate_size_t pos;
80 gate_uint64_t n;
81
82 pos = gate_string_char_pos(text, '~', 0);
83 if (pos != GATE_STR_NPOS)
84 {
85 n = 0;
86 gate_str_parse_uint64(gate_string_ptr(text, 0), pos, &n);
87 if (ptr_procid)
88 {
89 *ptr_procid = (DWORD)n;
90 }
91
92 n = 0;
93 gate_str_parse_uint64(gate_string_ptr(text, pos + 1), gate_string_length(text) - pos - 1, &n);
94 if (ptr_handle)
95 {
96 *ptr_handle = (HANDLE)(gate_uintptr_t)n;
97 }
98 ret = GATE_RESULT_OK;
99 }
100
101 return ret;
102 }
103
104
105 gate_result_t gate_ipcsharedmem_create(gate_ipcsharedmem_t* ptr_shmem, gate_size_t memsize, gate_enumint_t flags, gate_string_t* out_uid)
106 {
107 gate_result_t ret = GATE_RESULT_FAILED;
108 SECURITY_ATTRIBUTES sec_attrs = GATE_INIT_EMPTY;
109 gate_size_t total_size = sizeof(gate_ipcsharedmem_data_t) + memsize;
110 DWORD sz_low = 0, sz_high = 0;
111 HANDLE handle = NULL;
112 gate_ipcsharedmem_data_t* dataptr = NULL;
113 char uid_buffer[256];
114 gate_size_t uid_buffer_used = 0;
115
116 do
117 {
118 if ((memsize == 0) && (ptr_shmem == NULL))
119 {
120 ret = GATE_RESULT_INVALIDARG;
121 break;
122 }
123
124 sz_high = (DWORD)(((gate_uint64_t)memsize) >> 32);
125 sz_low = (DWORD)(memsize % 0xffffffff);
126
127 sec_attrs.nLength = sizeof(sec_attrs);
128 sec_attrs.lpSecurityDescriptor = NULL;
129 sec_attrs.bInheritHandle = TRUE;
130
131 handle = CreateFileMapping(INVALID_HANDLE_VALUE, &sec_attrs, PAGE_READWRITE, sz_high, sz_low, NULL);
132 if (NULL == handle)
133 {
134 ret = GATE_RESULT_OUTOFRESOURCES;
135 break;
136 }
137
138 dataptr = (gate_ipcsharedmem_data_t*)MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, total_size);
139 if (NULL == dataptr)
140 {
141 ret = GATE_RESULT_OUTOFRESOURCES;
142 break;
143 }
144 gate_mem_clear(dataptr, total_size);
145 dataptr->version = GATE_IO_SHAREDMEM_VERSION_1;
146 dataptr->flags = flags;
147 dataptr->mem_size = memsize;
148
149 UnmapViewOfFile(dataptr);
150
151 if (out_uid)
152 {
153 uid_buffer_used = gate_ipcsharedmem_create_uid(handle, uid_buffer, sizeof(uid_buffer));
154 gate_string_create(out_uid, uid_buffer, uid_buffer_used);
155 }
156
157 *ptr_shmem = handle;
158 handle = NULL;
159
160 ret = GATE_RESULT_OK;
161 } while (0);
162
163 if (NULL != handle)
164 {
165 CloseHandle(handle);
166 }
167
168 return ret;
169 }
170 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)
171 {
172 gate_result_t ret = GATE_RESULT_FAILED;
173 DWORD proc_id = 0;
174 HANDLE hproc = GetCurrentProcess();
175 HANDLE src_handle = NULL;
176 HANDLE target_handle = NULL;
177 void* ptr_mem;
178 gate_ipcsharedmem_data_t info_data;
179
180 do
181 {
182 ret = gate_ipcsharedmem_parse_uid(uid, &proc_id, &src_handle);
183 GATE_BREAK_IF_FAILED(ret);
184
185 if (!DuplicateHandle(hproc, src_handle, hproc, &target_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
186 {
187 ret = GATE_RESULT_FAILED;
188 break;
189 }
190 ptr_mem = MapViewOfFile(target_handle, FILE_MAP_READ, 0, 0, sizeof(gate_ipcsharedmem_data_t));
191 if (!ptr_mem)
192 {
193 ret = GATE_RESULT_FAILED;
194 break;
195 }
196 info_data = *((gate_ipcsharedmem_data_t*)ptr_mem);
197 UnmapViewOfFile(ptr_mem);
198
199 if (out_memsize) *out_memsize = (gate_size_t)(info_data.mem_size);
200 if (out_flags) *out_flags = info_data.flags;
201
202 *ptr_shmem = (gate_ipcsharedmem_t)target_handle;
203 target_handle = NULL;
204 ret = GATE_RESULT_OK;
205
206 } while (0);
207
208 if (target_handle != NULL)
209 {
210 CloseHandle(target_handle);
211 }
212
213 return ret;
214 }
215 gate_result_t gate_ipcsharedmem_destroy(gate_ipcsharedmem_t shmem)
216 {
217 gate_result_t ret = GATE_RESULT_OK;
218 if (shmem)
219 {
220 if (!CloseHandle((HANDLE)shmem))
221 {
222 ret = GATE_RESULT_FAILED;
223 }
224 }
225 return ret;
226 }
227 gate_result_t gate_ipcsharedmem_attach(gate_ipcsharedmem_t shmem, void** ptr_dataptr)
228 {
229 HANDLE hmem = (HANDLE)shmem;
230 gate_ipcsharedmem_data_t* ptr_data = NULL;
231 void* ptr = MapViewOfFile((HANDLE)hmem, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
232 if (!ptr)
233 {
234 return GATE_RESULT_FAILED;
235 }
236 else
237 {
238 ptr_data = (gate_ipcsharedmem_data_t*)ptr;
239 if (ptr_dataptr)
240 {
241 *ptr_dataptr = (void*)&ptr_data->data;
242 }
243 else
244 {
245 UnmapViewOfFile(ptr);
246 }
247 return GATE_RESULT_OK;
248 }
249 }
250 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t shmem, void* dataptr)
251 {
252 static gate_size_t offset = offsetof(gate_ipcsharedmem_data_t, data);
253 char* root_ptr = ((char*)dataptr) - offset;
254 gate_ipcsharedmem_data_t* ptr_data = (gate_ipcsharedmem_data_t*)root_ptr;
255
256 GATE_UNUSED_ARG(shmem);
257
258 if (!dataptr)
259 {
260 return GATE_RESULT_INVALIDARG;
261 }
262
263 if (!UnmapViewOfFile((void*)ptr_data))
264 {
265 return GATE_RESULT_FAILED;
266 }
267 return GATE_RESULT_OK;
268 }
269
270 #endif /* GATE_IO_SHAREDMEM_WINAPI */
271
272
273
274
275 #if defined(GATE_IO_SHAREDMEM_POSIX)
276
277 #include "gate/platforms.h"
278 #include "gate/utilities.h"
279 #include <sys/shm.h>
280
281 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)
282 {
283 2 gate_result_t ret = GATE_RESULT_FAILED;
284 int id;
285 gate_ipcsharedmem_data_t* ptr;
286 int err_code;
287 2 gate_size_t total_size = sizeof(gate_ipcsharedmem_data_t) + memsize;
288
289 do
290 {
291 2 id = shmget(IPC_PRIVATE, total_size, IPC_CREAT | SHM_R | SHM_W);
292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (id == -1)
293 {
294 err_code = gate_posix_errno(&ret);
295 break;
296 }
297
298 2 ptr = (gate_ipcsharedmem_data_t*)shmat(id, NULL, 0);
299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ptr == ((void*)-1))
300 {
301 err_code = gate_posix_errno(&ret);
302 shmctl(id, IPC_RMID, NULL);
303 break;
304 }
305
306 2 gate_mem_clear(ptr, total_size);
307 2 ptr->version = GATE_IO_SHAREDMEM_VERSION_1;
308 2 ptr->flags = flags;
309 2 ptr->mem_size = memsize;
310
311 2 shmdt((void*)ptr);
312
313
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (out_uid != NULL)
314 {
315
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_util_int_to_string(out_uid, id))
316 {
317 ret = GATE_RESULT_OUTOFMEMORY;
318 shmctl(id, IPC_RMID, NULL);
319 break;
320 }
321 }
322
323 2 *ptr_ipc_mem = (void*)(gate_intptr_t)id;
324 2 ret = GATE_RESULT_OK;
325 } while (0);
326
327 2 return ret;
328 }
329 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)
330 {
331 gate_result_t ret = GATE_RESULT_FAILED;
332 gate_int64_t parsed_id;
333 int id;
334 int err_code;
335 gate_ipcsharedmem_data_t* ptr;
336
337 do
338 {
339 if (0 == gate_str_parse_int64(uid->str, uid->length, &parsed_id))
340 {
341 ret = GATE_RESULT_INVALIDARG;
342 break;
343 }
344 id = (int)parsed_id;
345 ptr = shmat(id, NULL, 0);
346 if (((void*)ptr) == ((void*)-1))
347 {
348 err_code = gate_posix_errno(&ret);
349 break;
350 }
351
352 if (out_memsize)
353 {
354 *out_memsize = ptr->mem_size;
355 }
356 if (out_flags)
357 {
358 *out_flags = ptr->flags;
359 }
360 shmdt((void*)ptr);
361
362 *ptr_ipc_mem = (void*)(gate_intptr_t)id;
363 ret = GATE_RESULT_OK;
364 } while (0);
365
366 return ret;
367 }
368 2 gate_result_t gate_ipcsharedmem_destroy(gate_ipcsharedmem_t shmem)
369 {
370 2 gate_result_t ret = GATE_RESULT_OK;
371 2 int id = (int)(intptr_t)shmem;
372 do
373 {
374 2 shmctl(id, IPC_RMID, NULL);
375 2 ret = GATE_RESULT_OK;
376 } while (0);
377
378 2 return ret;
379 }
380 2 gate_result_t gate_ipcsharedmem_attach(gate_ipcsharedmem_t shmem, void** ptr_dataptr)
381 {
382 2 gate_result_t ret = GATE_RESULT_FAILED;
383 2 int id = (int)(intptr_t)shmem;
384 2 gate_ipcsharedmem_data_t* ptr = NULL;
385
386 do
387 {
388 2 ptr = (gate_ipcsharedmem_data_t*)shmat(id, NULL, 0);
389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (((void*)ptr) == ((void*)-1))
390 {
391 ret = GATE_RESULT_FAILED;
392 break;
393 }
394
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptr_dataptr)
395 {
396 2 *ptr_dataptr = (void*)(ptr + 1);
397 }
398 2 ret = GATE_RESULT_OK;
399 } while (0);
400 2 return ret;
401 }
402 2 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t handle, void* dataptr)
403 {
404 2 gate_result_t ret = GATE_RESULT_FAILED;
405 gate_ipcsharedmem_data_t* ptr;
406 do
407 {
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (dataptr == NULL)
409 {
410 ret = GATE_RESULT_NULLPOINTER;
411 break;
412 }
413 2 ptr = (gate_ipcsharedmem_data_t*)dataptr;
414 2 --ptr;
415 2 shmdt((void*)ptr);
416 2 ret = GATE_RESULT_OK;
417 } while (0);
418 2 return ret;
419 }
420
421 #endif /* GATE_IO_SHAREDMEM_POSIX */
422
423
424
425
426 #if defined(GATE_IO_SHAREDMEM_NO_IMPL)
427
428 gate_result_t gate_ipcsharedmem_create(gate_ipcsharedmem_t* mem, gate_size_t memsize, gate_enumint_t flags, gate_string_t* out_uid)
429 {
430 (void)mem;
431 (void)memsize;
432 (void)flags;
433 (void)out_uid;
434 return GATE_RESULT_NOTIMPLEMENTED;
435 }
436 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)
437 {
438 (void)mem;
439 (void)uid;
440 (void)out_memsize;
441 (void)out_flags;
442 return GATE_RESULT_NOTIMPLEMENTED;
443 }
444 gate_result_t gate_ipcsharedmem_destroy(gate_ipcsharedmem_t handle)
445 {
446 (void)handle;
447 return GATE_RESULT_NOTIMPLEMENTED;
448 }
449 gate_result_t gate_ipcsharedmem_attach(gate_ipcsharedmem_t handle, void** ptr_dataptr)
450 {
451 (void)handle;
452 (void)ptr_dataptr;
453 return GATE_RESULT_NOTIMPLEMENTED;
454 }
455 gate_result_t gate_ipcsharedmem_detach(gate_ipcsharedmem_t handle, void* dataptr)
456 {
457 (void)handle;
458 (void)dataptr;
459 return GATE_RESULT_NOTIMPLEMENTED;
460 }
461
462 #endif /* GATE_IO_SHAREDMEM_NO_IMPL */
463
464