GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/virtualization.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 18 208 8.7%
Functions: 3 27 11.1%
Branches: 6 86 7.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, Stefan Meislinger |
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/tech/virtualization.h"
30
31 #include "gate/results.h"
32
33
34 static gate_string_t const virtprov_name_lxc = GATE_STRING_INIT_STATIC("lxc");
35 static gate_string_t const virtprov_descr_lxc = GATE_STRING_INIT_STATIC("Linux-Containers");
36
37 static gate_string_t const virtprov_name_docker = GATE_STRING_INIT_STATIC("docker");
38 static gate_string_t const virtprov_descr_docker = GATE_STRING_INIT_STATIC("Docker");
39
40 #if defined(GATE_SYS_LINUX)
41 # define GATE_TECH_VIRTUALIZATION_LXC 1
42 #endif
43
44 #if defined(GATE_SYS_WIN) && !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
45 # define GATE_TECH_VIRTUALIZATION_HYPERV2 1
46 # define GATE_TECH_VIRTUALIZATION_WSL 1
47 #endif
48
49 #define GATE_TECH_VIRTUALIZATION_DOCKER 1
50
51
52
53
54 #if defined(GATE_TECH_VIRTUALIZATION_LXC)
55
56 #include <stdlib.h>
57
58 #include "gate/tech/platform/gate_lxc.h"
59 #include "gate/utilities.h"
60 #include "gate/debugging.h"
61
62 static gate_lxc_functions_t lxc_code;
63 static gate_bool_t lxc_code_init;
64
65 1 static gate_result_t gate_lxc_init()
66 {
67 1 gate_result_t ret = GATE_RESULT_OK;
68
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!lxc_code_init)
69 {
70 1 ret = gate_load_lxc_functions(&lxc_code);
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_SUCCEEDED(ret))
72 {
73 lxc_code_init = true;
74 }
75 }
76 1 return ret;
77 }
78
79 static void free_lxc_array(void** array, int count)
80 {
81 while(count-- > 0)
82 {
83 free(*array);
84 ++array;
85 }
86 }
87
88 /* LXC sandbox interface methods */
89
90 typedef struct lxcsbox_class
91 {
92 GATE_INTERFACE_VTBL(gate_virtualization_sandbox) const* vtbl;
93
94 gate_atomic_int_t ref_counter;
95 gate_string_t name;
96 gate_property_t settings;
97 } lxcsbox_t;
98
99 static void lxcsbox_destroy(lxcsbox_t* self)
100 {
101 gate_string_release(&self->name);
102 gate_property_destroy(&self->settings);
103 gate_mem_dealloc(self);
104 }
105
106 static char const* lxcsbox_get_interface_name(void* thisptr)
107 {
108 GATE_UNUSED_ARG(thisptr);
109 return GATE_INTERFACE_NAME_VIRTUALIZATION_SANDBOX;
110 }
111
112 static void lxcsbox_release(void* thisptr)
113 {
114 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
115 if (gate_atomic_int_dec(&self->ref_counter) == 0)
116 {
117 lxcsbox_destroy(self);
118 }
119 }
120
121 static int lxcsbox_retain(void* thisptr)
122 {
123 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
124 return gate_atomic_int_inc(&self->ref_counter);
125 }
126
127 static gate_result_t get_lxc_container_from_sandbox(lxcsbox_t* self, struct lxc_container** ptr_container)
128 {
129 gate_result_t ret;
130 gate_cstrbuffer_t buffer = GATE_INIT_EMPTY;
131 struct lxc_container* container = NULL;
132 do
133 {
134 if (NULL == gate_cstrbuffer_create_string(&buffer, &self->name, false))
135 {
136 GATE_DEBUG_TRACE("gate_cstrbuffer_create_string() failed");
137 ret = GATE_RESULT_OUTOFMEMORY;
138 break;
139 }
140 container = lxc_code.lxc_container_new(gate_cstrbuffer_get(&buffer), NULL);
141 if (NULL == container)
142 {
143 GATE_DEBUG_TRACE("lxc_container_new() failed");
144 ret = GATE_RESULT_FAILED;
145 break;
146 }
147 ret = GATE_RESULT_OK;
148 } while (0);
149 gate_cstrbuffer_destroy(&buffer);
150 *ptr_container = container;
151 return ret;
152 }
153
154 static void release_container(struct lxc_container** ptr_container)
155 {
156 GATE_DEBUG_ASSERT(ptr_container != NULL);
157 if (NULL != *ptr_container)
158 {
159 lxc_code.lxc_container_put(*ptr_container);
160 *ptr_container = NULL;
161 }
162 }
163
164 static gate_result_t lxcsbox_start(void* thisptr)
165 {
166 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
167 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
168 struct lxc_container* ptr_container = NULL;
169 do
170 {
171 ret = get_lxc_container_from_sandbox(self, &ptr_container);
172 GATE_BREAK_IF_FAILED(ret);
173
174 if (!ptr_container->is_defined(ptr_container))
175 {
176 /* container not defined/existing */
177 ret = GATE_RESULT_NOTAVAILABLE;
178 break;
179 }
180
181 if (ptr_container->is_running(ptr_container))
182 {
183 /* container is already started -> start not supported */
184 ret = GATE_RESULT_INVALIDSTATE;
185 break;
186 }
187
188 if (!ptr_container->start(ptr_container, 0, NULL))
189 {
190 /* failed to start container */
191 ret = GATE_RESULT_FAILED;
192 break;
193 }
194
195 /* success case */
196 ret = GATE_RESULT_OK;
197 } while (0);
198
199 release_container(&ptr_container);
200 return ret;
201 }
202
203 static gate_result_t lxcsbox_stop(void* thisptr)
204 {
205 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
206 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
207 struct lxc_container* ptr_container = NULL;
208 do
209 {
210 ret = get_lxc_container_from_sandbox(self, &ptr_container);
211 GATE_BREAK_IF_FAILED(ret);
212
213 if (!ptr_container->is_defined(ptr_container))
214 {
215 /* container not defined/existing */
216 ret = GATE_RESULT_NOTAVAILABLE;
217 break;
218 }
219
220 if (!ptr_container->is_running(ptr_container))
221 {
222 /* conainter is not running, stop not supported */
223 ret = GATE_RESULT_INVALIDSTATE;
224 break;
225 }
226
227 if (!ptr_container->stop(ptr_container))
228 {
229 /* failed to stop container */
230 ret = GATE_RESULT_FAILED;
231 break;
232 }
233
234 /* success case */
235 ret = GATE_RESULT_OK;
236 } while (0);
237
238 release_container(&ptr_container);
239 return ret;
240 }
241
242 static gate_enumint_t lxcsbox_get_status(void* thisptr)
243 {
244 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
245 gate_enumint_t ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
246 struct lxc_container* ptr_container = NULL;
247 do
248 {
249 gate_result_t result = get_lxc_container_from_sandbox(self, &ptr_container);
250 GATE_BREAK_IF_FAILED(result);
251
252 if (!ptr_container->is_defined(ptr_container))
253 {
254 /* container not defined/existing */
255 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
256 }
257 else
258 {
259 /* evaluate running state */
260 ret = ptr_container->is_running(ptr_container)
261 ? GATE_VIRTUALIZATION_SANDBOX_STATUS_ONLINE
262 : GATE_VIRTUALIZATION_SANDBOX_STATUS_OFFLINE
263 ;
264 }
265 } while (0);
266 release_container(&ptr_container);
267 return ret;
268 }
269
270 static gate_result_t lxcsbox_get_id(void* thisptr, gate_string_t* id)
271 {
272 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
273 if (id)
274 {
275 gate_string_clone(id, &self->name);
276 }
277 return GATE_RESULT_OK;
278 }
279
280 static gate_result_t lxcsbox_get_name(void* thisptr, gate_string_t* name)
281 {
282 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
283 if (name)
284 {
285 gate_string_clone(name, &self->name);
286 }
287 return GATE_RESULT_OK;
288 }
289
290 static gate_result_t lxcsbox_get_settings(void* thisptr, gate_property_t* settings)
291 {
292 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
293 if (settings)
294 {
295 if (NULL == gate_property_copy(settings, &self->settings))
296 {
297 return GATE_RESULT_OUTOFMEMORY;
298 }
299 }
300 return GATE_RESULT_OK;
301 }
302
303 static gate_result_t lxcsbox_update_settings(void* thisptr, gate_property_t const* settings)
304 {
305 lxcsbox_t* const self = (lxcsbox_t*)thisptr;
306 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
307 (void)self;
308 /* TODO */
309 return ret;
310 }
311
312 static GATE_INTERFACE_VTBL(gate_virtualization_sandbox) const* lxcsbox_vtbl_init()
313 {
314 static GATE_INTERFACE_VTBL(gate_virtualization_sandbox) lxcsbox_vtbl;
315 if (lxcsbox_vtbl.get_interface_name == NULL)
316 {
317 GATE_INTERFACE_VTBL(gate_virtualization_sandbox) const vtbl = {
318 &lxcsbox_get_interface_name,
319 &lxcsbox_release,
320 &lxcsbox_retain,
321
322 &lxcsbox_start,
323 &lxcsbox_stop,
324 &lxcsbox_get_status,
325
326 &lxcsbox_get_id,
327 &lxcsbox_get_name,
328 &lxcsbox_get_settings,
329 &lxcsbox_update_settings
330 };
331 lxcsbox_vtbl = vtbl;
332 }
333 return &lxcsbox_vtbl;
334 }
335
336 static gate_result_t lxcsbox_create(gate_string_t const* name, lxcsbox_t** ptr_lxcsbox)
337 {
338 lxcsbox_t* ptr = (lxcsbox_t*)gate_mem_alloc(sizeof(lxcsbox_t));
339 if (NULL == ptr)
340 {
341 return GATE_RESULT_OUTOFMEMORY;
342 }
343 gate_mem_clear(ptr, sizeof(lxcsbox_t));
344 ptr->vtbl = lxcsbox_vtbl_init();
345 gate_atomic_int_init(&ptr->ref_counter, 1);
346 gate_string_clone(&ptr->name, name);
347 gate_property_create_object(&ptr->settings);
348 *ptr_lxcsbox = ptr;
349 return GATE_RESULT_OK;
350 }
351
352
353
354 /* LXC provider interface methods */
355
356 static char const* lxcprov_get_interface_name(void* obj)
357 {
358 GATE_UNUSED_ARG(obj);
359 return GATE_INTERFACE_NAME_VIRTUALIZATION_PROVIDER;
360 }
361 static void lxcprov_release(void* obj)
362 {
363 GATE_UNUSED_ARG(obj);
364 }
365 static int lxcprov_retain(void* obj)
366 {
367 GATE_UNUSED_ARG(obj);
368 return 1;
369 }
370 static gate_result_t lxcprov_get_name(void* obj, gate_string_t* name)
371 {
372 GATE_UNUSED_ARG(obj);
373 gate_string_create_static_len(name, "LXC", 3);
374 return GATE_RESULT_OK;
375 }
376 static gate_result_t lxcprov_get_settings(void* obj, gate_property_t* settings)
377 {
378 GATE_UNUSED_ARG(obj);
379 gate_property_create_object(settings);
380 return GATE_RESULT_OK;
381 }
382 static gate_result_t lxcprov_list_sandbox_ids(void* obj, gate_array_t* sandbox_ids)
383 {
384 GATE_UNUSED_ARG(obj);
385 gate_result_t ret = GATE_RESULT_FAILED;
386 char** names = NULL;
387 int found_containers;
388 gate_arraylist_t arr = NULL;
389
390 do
391 {
392 gate_size_t ndx;
393 char const* const lxcpath = NULL;
394 found_containers = lxc_code.list_all_containers(lxcpath, &names, NULL);
395 if (found_containers < 0)
396 {
397 ret = GATE_RESULT_FAILED;
398 break;
399 }
400
401 arr = gate_util_stringarray_create();
402 if (arr == NULL)
403 {
404 ret = GATE_RESULT_OUTOFMEMORY;
405 break;
406 }
407
408 for (ndx = 0; ndx < found_containers; ++ndx)
409 {
410 char const* name = names[ndx];
411 gate_util_stringarray_add_str(arr, name);
412 }
413
414 ret = GATE_RESULT_OK;
415 if (sandbox_ids)
416 {
417 if (NULL == gate_array_create(sandbox_ids, arr))
418 {
419 ret = GATE_RESULT_OUTOFMEMORY;
420 }
421 }
422 } while (0);
423
424 if (arr)
425 {
426 gate_arraylist_release(arr);
427 }
428 if (names)
429 {
430 free_lxc_array((void**)names, found_containers);
431 }
432
433 return ret;
434 }
435
436 static gate_result_t lxcprov_get_sandbox(void* obj, gate_string_t const* sandbox_id, gate_virtualization_sandbox_t** ptr_sandbox)
437 {
438 lxcsbox_t* ptr = NULL;
439 gate_result_t result = lxcsbox_create(sandbox_id, &ptr);
440 if (GATE_SUCCEEDED(result))
441 {
442 if (ptr_sandbox)
443 {
444 *ptr_sandbox = (gate_virtualization_sandbox_t*)ptr;
445 }
446 else
447 {
448 gate_object_release(ptr);
449 }
450 }
451 return result;
452 }
453
454
455 static gate_virtualization_provider_t* init_global_lxc_provider()
456 {
457 static gate_virtualization_provider_t lxc_prov;
458 static GATE_INTERFACE_VTBL(gate_virtualization_provider) lxc_prov_vtbl;
459
460 if (lxc_prov.vtbl == NULL)
461 {
462 GATE_INTERFACE_VTBL(gate_virtualization_provider) const vtbl = {
463 &lxcprov_get_interface_name,
464 &lxcprov_release,
465 &lxcprov_retain,
466
467 &lxcprov_get_name,
468 &lxcprov_get_settings,
469
470 &lxcprov_list_sandbox_ids,
471 &lxcprov_get_sandbox
472 };
473 lxc_prov_vtbl = vtbl;
474 lxc_prov.vtbl = &lxc_prov_vtbl;
475 }
476 return &lxc_prov;
477 }
478
479 #endif /* GATE_TECH_VIRTUALIZATION_LXC */
480
481
482
483 #if defined(GATE_TECH_VIRTUALIZATION_HYPERV2)
484
485 #include "gate/system/management.h"
486 #include "gate/utilities.h"
487
488 static gate_string_t const virtprov_name_hyperv2 = GATE_STRING_INIT_STATIC("mshyperv2");
489 static gate_string_t const virtprov_descr_hyperv2 = GATE_STRING_INIT_STATIC("Microsoft Hyper-V v2");
490
491 static gate_string_t const wmi_default_host = GATE_STRING_INIT_STATIC(".");
492 static gate_string_t const wmi_default_namespace = GATE_STRING_INIT_STATIC("ROOT\\virtualization\\v2");
493 static gate_string_t const wmi_search_path = GATE_STRING_INIT_STATIC("\\\\.\\ROOT\\virtualization\\v2");
494
495
496 typedef struct mshv2sbox_class
497 {
498 GATE_INTERFACE_VTBL(gate_virtualization_sandbox) const* vtbl;
499
500 gate_atomic_int_t ref_counter;
501 gate_management_t mgmt;
502 gate_string_t vm_path;
503 } mshv2sbox_t;
504
505 static void mshv2sbox_destroy(mshv2sbox_t* self)
506 {
507 if (self->mgmt)
508 {
509 gate_management_close(self->mgmt);
510 }
511 gate_string_release(&self->vm_path);
512
513 gate_mem_clear(self, sizeof(mshv2sbox_t));
514 gate_mem_dealloc(self);
515 }
516
517 static char const* mshv2sbox_get_interface_name(void* thisptr)
518 {
519 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
520 return GATE_INTERFACE_NAME_VIRTUALIZATION_SANDBOX;
521 }
522 static void mshv2sbox_release(void* thisptr)
523 {
524 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
525 if (gate_atomic_int_dec(&self->ref_counter) == 0)
526 {
527 mshv2sbox_destroy(self);
528 }
529 }
530 static int mshv2sbox_retain(void* thisptr)
531 {
532 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
533 return gate_atomic_int_inc(&self->ref_counter);
534 }
535
536
537 static gate_result_t mshv2sbox_change_state(mshv2sbox_t* self, gate_int32_t new_state)
538 {
539 gate_result_t ret;
540 gate_map_t input_args = GATE_INIT_EMPTY;
541 gate_map_t output_args = GATE_INIT_EMPTY;
542 do
543 {
544 static gate_string_t const methodname = GATE_STRING_INIT_STATIC("RequestStateChange");
545 static gate_string_t const param_requestedstate = GATE_STRING_INIT_STATIC("RequestedState");
546 static gate_string_t const param_returnvalue = GATE_STRING_INIT_STATIC("ReturnValue");
547 gate_value_t const* ptr_retval = NULL;
548
549 if (NULL == gate_util_stringvaluemap_create_ex(&input_args, true, true))
550 {
551 ret = GATE_RESULT_OUTOFMEMORY;
552 break;
553 }
554 gate_util_stringvaluemap_add_string(&input_args, &param_requestedstate, GATE_TYPE_I32, &new_state);
555
556 ret = gate_management_invoke(self->mgmt, &self->vm_path, &methodname, &input_args, &output_args);
557 GATE_BREAK_IF_FAILED(ret);
558
559 ptr_retval = gate_util_stringvaluemap_get_string(&output_args, &param_returnvalue);
560 if (ptr_retval)
561 {
562 /* evaluate WMI return value */
563 gate_int32_t const* ptr_intretval = (gate_int32_t const*)gate_value_get_ptr(ptr_retval);
564 if (ptr_intretval)
565 {
566 gate_int32_t const rv = *ptr_intretval;
567 if ((rv == 0) || (rv == 4096))
568 {
569 ret = GATE_RESULT_OK;
570 }
571 else
572 {
573 ret = GATE_RESULT_EXECUTIONFAILED;
574 }
575 }
576 }
577 } while (0);
578
579 gate_map_destroy(&input_args);
580 gate_map_destroy(&output_args);
581 return ret;
582 }
583
584 static gate_result_t mshv2sbox_start(void* thisptr)
585 {
586 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
587 static int const state_enabled = 2;
588 return mshv2sbox_change_state(self, state_enabled);
589 }
590 static gate_result_t mshv2sbox_stop(void* thisptr)
591 {
592 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
593 static int const state_disabled = 3;
594 return mshv2sbox_change_state(self, state_disabled);
595 }
596
597 #define MSHV2SBOX_STATE_UNKNOWN 0
598 #define MSHV2SBOX_STATE_OTHER 1
599 #define MSHV2SBOX_STATE_ENABLED 2
600 #define MSHV2SBOX_STATE_DISABLED 3
601 #define MSHV2SBOX_STATE_SHUTDOWN 4
602 #define MSHV2SBOX_STATE_NOTAPPLICABLE 5
603 #define MSHV2SBOX_STATE_OFFLINE 6
604 #define MSHV2SBOX_STATE_TEST 7
605 #define MSHV2SBOX_STATE_DEFERRED 8
606 #define MSHV2SBOX_STATE_QUIESCE 9
607 #define MSHV2SBOX_STATE_STARTING 10
608
609 static gate_enumint_t mshv2sbox_get_status(void* thisptr)
610 {
611 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
612 gate_management_object_t obj = GATE_INIT_EMPTY;
613 gate_enumint_t ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
614
615 do
616 {
617 static gate_string_t const keyEnabledState = GATE_STRING_INIT_STATIC("EnabledState");
618 gate_map_iterator_t iter;
619 gate_result_t result = gate_management_get_object(self->mgmt, &self->vm_path, &obj);
620 GATE_BREAK_IF_FAILED(result);
621
622 iter = gate_map_get(&obj.properties, &keyEnabledState);
623 if (!gate_map_iterator_valid(iter))
624 {
625 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
626 break;
627 }
628 else
629 {
630 gate_value_t const* ptr_value = (gate_value_t const*)gate_map_iterator_value(iter);
631 gate_int32_t const* ptr_state;
632 if (gate_value_type(ptr_value) != GATE_TYPE_I32)
633 {
634 break;
635 }
636 ptr_state = (gate_int32_t const*)gate_value_get_ptr(ptr_value);
637 switch (*ptr_state)
638 {
639 case MSHV2SBOX_STATE_UNKNOWN:
640 case MSHV2SBOX_STATE_OTHER:
641 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_UNKNOWN;
642 break;
643 case MSHV2SBOX_STATE_ENABLED:
644 case MSHV2SBOX_STATE_QUIESCE:
645 case MSHV2SBOX_STATE_OFFLINE:
646 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_ONLINE;
647 break;
648 case MSHV2SBOX_STATE_DISABLED:
649 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_OFFLINE;
650 break;
651 case MSHV2SBOX_STATE_SHUTDOWN:
652 case MSHV2SBOX_STATE_NOTAPPLICABLE:
653 case MSHV2SBOX_STATE_TEST:
654 case MSHV2SBOX_STATE_DEFERRED:
655 case MSHV2SBOX_STATE_STARTING:
656 ret = GATE_VIRTUALIZATION_SANDBOX_STATUS_BUSY;
657 break;
658 }
659 }
660 } while (0);
661
662 gate_management_object_release(&obj);
663 return ret;
664 }
665
666 static gate_result_t mshv2sbox_get_id(void* thisptr, gate_string_t* id)
667 {
668 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
669 gate_result_t ret;
670 gate_management_object_t obj = GATE_INIT_EMPTY;
671
672 do
673 {
674 static gate_string_t const keyName = GATE_STRING_INIT_STATIC("Name");
675 gate_map_iterator_t iter;
676 gate_value_t const* value;
677 gate_string_t const* strvalue;
678
679 ret = gate_management_get_object(self->mgmt, &self->vm_path, &obj);
680 GATE_BREAK_IF_FAILED(ret);
681
682 iter = gate_map_get(&obj.properties, &keyName);
683 if (!gate_map_iterator_valid(iter))
684 {
685 ret = GATE_RESULT_NOTAVAILABLE;
686 break;
687 }
688 value = (gate_value_t const*)gate_map_iterator_value(iter);
689 if (gate_value_type(value) != GATE_TYPE_STRING)
690 {
691 ret = GATE_RESULT_INCORRECTTYPE;
692 break;
693 }
694 strvalue = (gate_string_t const*)gate_value_get_ptr(value);
695 if (NULL == gate_string_clone(id, strvalue))
696 {
697 ret = GATE_RESULT_OUTOFMEMORY;
698 break;
699 }
700 ret = GATE_RESULT_OK;
701 } while (0);
702 gate_management_object_release(&obj);
703 return ret;
704 }
705 static gate_result_t mshv2sbox_get_name(void* thisptr, gate_string_t* name)
706 {
707 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
708 gate_result_t ret;
709 gate_management_object_t obj = GATE_INIT_EMPTY;
710
711 do
712 {
713 static gate_string_t const keyName = GATE_STRING_INIT_STATIC("ElementName");
714 gate_map_iterator_t iter;
715 gate_value_t const* value;
716 gate_string_t const* strvalue;
717
718 ret = gate_management_get_object(self->mgmt, &self->vm_path, &obj);
719 GATE_BREAK_IF_FAILED(ret);
720
721 iter = gate_map_get(&obj.properties, &keyName);
722 if (!gate_map_iterator_valid(iter))
723 {
724 ret = GATE_RESULT_NOTAVAILABLE;
725 break;
726 }
727 value = (gate_value_t const*)gate_map_iterator_value(iter);
728 if (gate_value_type(value) != GATE_TYPE_STRING)
729 {
730 ret = GATE_RESULT_INCORRECTTYPE;
731 break;
732 }
733 strvalue = (gate_string_t const*)gate_value_get_ptr(value);
734 if (NULL == gate_string_clone(name, strvalue))
735 {
736 ret = GATE_RESULT_OUTOFMEMORY;
737 break;
738 }
739 ret = GATE_RESULT_OK;
740 } while (0);
741 gate_management_object_release(&obj);
742 return ret;
743 }
744 static gate_result_t mshv2sbox_get_settings(void* thisptr, gate_property_t* settings)
745 {
746 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
747 gate_result_t ret;
748 do
749 {
750 if (NULL == gate_property_create_object(settings))
751 {
752 ret = GATE_RESULT_OUTOFMEMORY;
753 break;
754 }
755 /* TODO */
756 ret = GATE_RESULT_OK;
757 } while (0);
758 return ret;
759 }
760 static gate_result_t mshv2sbox_update_settings(void* thisptr, gate_property_t const* settings)
761 {
762 mshv2sbox_t* const self = (mshv2sbox_t*)thisptr;
763 gate_result_t ret;
764 do
765 {
766 /* TODO */
767 ret = GATE_RESULT_NOTSUPPORTED;
768 } while (0);
769 return ret;
770 }
771
772 static GATE_INTERFACE_VTBL(gate_virtualization_sandbox)* mshv2sbox_vtbl_init()
773 {
774 static GATE_INTERFACE_VTBL(gate_virtualization_sandbox) vtbl;
775 if (vtbl.get_interface_name == NULL)
776 {
777 GATE_INTERFACE_VTBL(gate_virtualization_sandbox) v =
778 {
779 &mshv2sbox_get_interface_name,
780 &mshv2sbox_release,
781 &mshv2sbox_retain,
782
783 &mshv2sbox_start,
784 &mshv2sbox_stop,
785 &mshv2sbox_get_status,
786
787 &mshv2sbox_get_id,
788 &mshv2sbox_get_name,
789 &mshv2sbox_get_settings,
790 &mshv2sbox_update_settings
791 };
792 vtbl = v;
793 }
794 return &vtbl;
795 }
796
797
798 static gate_result_t mshv2sbox_create(gate_string_t const* path, mshv2sbox_t** ptr_obj)
799 {
800 gate_result_t ret;
801 gate_management_t mgmt;
802 mshv2sbox_t* sbox = NULL;
803
804 do
805 {
806 sbox = (mshv2sbox_t*)gate_mem_alloc(sizeof(mshv2sbox_t));
807 if (sbox == NULL)
808 {
809 ret = GATE_RESULT_OUTOFMEMORY;
810 break;
811 }
812
813 gate_mem_clear(sbox, sizeof(mshv2sbox_t));
814 sbox->vtbl = mshv2sbox_vtbl_init();
815 gate_atomic_int_init(&sbox->ref_counter, 1);
816
817 gate_string_clone(&sbox->vm_path, path);
818 ret = gate_management_open(&wmi_default_host, NULL, &wmi_default_namespace, 0, &sbox->mgmt);
819 GATE_BREAK_IF_FAILED(ret);
820
821 *ptr_obj = sbox;
822 sbox = NULL;
823 ret = GATE_RESULT_OK;
824 } while (0);
825
826 if (sbox != NULL)
827 {
828 mshv2sbox_destroy(sbox);
829 }
830
831 return ret;
832 }
833
834
835 typedef struct mshv2prov_class
836 {
837 GATE_INTERFACE_VTBL(gate_virtualization_provider) const* vtbl;
838
839 gate_atomic_int_t ref_counter;
840 gate_management_t mgmt;
841 } mshv2prov_t;
842
843 static void mshv2prov_destroy(mshv2prov_t* self)
844 {
845 if (NULL != self->mgmt)
846 {
847 gate_management_close(self->mgmt);
848 }
849 gate_mem_clear(self, sizeof(mshv2prov_t));
850 gate_mem_dealloc(self);
851 }
852
853 static char const* mshv2prov_get_interface_name(void* thisptr)
854 {
855 mshv2prov_t* self = (mshv2prov_t*)thisptr;
856 return GATE_INTERFACE_NAME_VIRTUALIZATION_PROVIDER;
857 }
858
859 static void mshv2prov_release(void* thisptr)
860 {
861 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
862 if (0 == gate_atomic_int_dec(&self->ref_counter))
863 {
864 mshv2prov_destroy(self);
865 }
866 }
867
868 static int mshv2prov_retain(void* thisptr)
869 {
870 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
871 return gate_atomic_int_inc(&self->ref_counter);
872 }
873
874 static gate_result_t mshv2prov_get_name(void* thisptr, gate_string_t* name)
875 {
876 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
877 gate_string_duplicate(name, &virtprov_name_hyperv2);
878 return GATE_RESULT_OK;
879 }
880
881 static gate_result_t mshv2prov_get_settings(void* thisptr, gate_property_t* settings)
882 {
883 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
884 if (NULL == gate_property_create_object(settings))
885 {
886 return GATE_RESULT_OUTOFMEMORY;
887 }
888 return GATE_RESULT_OK;
889 }
890
891 static gate_bool_t GATE_CALL mshv2prov_list_callback(gate_management_object_t const* mgmt_obj, void* user_param)
892 {
893 gate_arraylist_t lst = (gate_arraylist_t)user_param;
894 static gate_string_t const keyInstallDate = GATE_STRING_INIT_STATIC("InstallDate");
895 static gate_string_t const keyName = GATE_STRING_INIT_STATIC("Name");
896 gate_map_iterator_t iterDate = gate_map_get(&mgmt_obj->properties, &keyInstallDate);
897 gate_map_iterator_t iterName = gate_map_get(&mgmt_obj->properties, &keyName);
898 if (gate_map_iterator_valid(iterDate) && gate_map_iterator_valid(iterName))
899 {
900 gate_value_t const* val_name = gate_map_iterator_value(iterName);
901 if (val_name && (gate_value_type(val_name) == GATE_TYPE_STRING))
902 {
903 gate_string_t const* name = (gate_string_t const*)gate_value_get_ptr(val_name);
904 gate_arraylist_add(lst, name);
905 }
906 }
907 return true;
908 }
909
910 static gate_string_t const search_query = GATE_STRING_INIT_STATIC("SELECT * FROM Msvm_ComputerSystem");
911
912 static gate_result_t mshv2prov_list_sandbox_ids(void* thisptr, gate_array_t* sandbox_ids)
913 {
914 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
915 gate_result_t ret;
916 gate_arraylist_t lst = gate_util_stringarray_create();
917
918 do
919 {
920 if (NULL == lst)
921 {
922 ret = GATE_RESULT_OUTOFMEMORY;
923 break;
924 }
925
926 ret = gate_management_query(self->mgmt, &wmi_search_path, &search_query, &mshv2prov_list_callback, lst);
927 GATE_BREAK_IF_FAILED(ret);
928
929 if (NULL == gate_array_create(sandbox_ids, lst))
930 {
931 ret = GATE_RESULT_OUTOFMEMORY;
932 break;
933 }
934
935 ret = GATE_RESULT_OK;
936 } while (0);
937
938 if (NULL != lst)
939 {
940 gate_arraylist_release(lst);
941 }
942
943 return ret;
944 }
945
946 static gate_bool_t GATE_CALL mshv2prov_sandbox_callback(gate_management_object_t const* mgmt_obj, void* user_param)
947 {
948 gate_string_t* path = (gate_string_t*)user_param;
949 gate_string_clone(path, &mgmt_obj->path);
950 return false;
951 }
952
953 static gate_result_t mshv2prov_get_sandbox(void* thisptr, gate_string_t const* sandbox_id, gate_virtualization_sandbox_t** ptr_sandbox)
954 {
955 mshv2prov_t* const self = (mshv2prov_t*)thisptr;
956 mshv2sbox_t* mshv2sbox = NULL;
957 gate_result_t result;
958 gate_strbuilder_t builder;
959 gate_string_t query = GATE_STRING_INIT_EMPTY;
960 gate_string_t found_path = GATE_STRING_INIT_EMPTY;
961 char buffer[1024];
962
963 do
964 {
965 gate_strbuilder_create_static(&builder, buffer, sizeof(buffer), 0);
966
967 gate_strbuilder_append_string(&builder, &search_query);
968 gate_strbuilder_append_cstr(&builder, " WHERE Name=\"");
969 gate_strbuilder_append_string(&builder, sandbox_id);
970 gate_strbuilder_append_cstr(&builder, "\"");
971
972 if (NULL == gate_strbuilder_to_string(&builder, &query))
973 {
974 result = GATE_RESULT_OUTOFMEMORY;
975 break;
976 }
977
978 result = gate_management_query(self->mgmt, &wmi_search_path, &query, &mshv2prov_sandbox_callback, &found_path);
979 GATE_BREAK_IF_FAILED(result);
980
981 if (gate_string_is_empty(&found_path))
982 {
983 result = GATE_RESULT_NOMATCH;
984 break;
985 }
986
987 result = mshv2sbox_create(&found_path, &mshv2sbox);
988 if (GATE_SUCCEEDED(result))
989 {
990 if (ptr_sandbox)
991 {
992 *ptr_sandbox = (gate_virtualization_sandbox_t*)mshv2sbox;
993 }
994 else
995 {
996 gate_object_release(mshv2sbox);
997 }
998 }
999 } while (0);
1000
1001 gate_string_release(&found_path);
1002 gate_string_release(&query);
1003 gate_strbuilder_release(&builder);
1004
1005 return result;
1006 }
1007
1008 static GATE_INTERFACE_VTBL(gate_virtualization_provider) const* init_virutalization_provider_vtbl()
1009 {
1010 static GATE_INTERFACE_VTBL(gate_virtualization_provider) vtbl;
1011 if (vtbl.get_interface_name == NULL)
1012 {
1013 GATE_INTERFACE_VTBL(gate_virtualization_provider) v =
1014 {
1015 &mshv2prov_get_interface_name,
1016 &mshv2prov_release,
1017 &mshv2prov_retain,
1018
1019 &mshv2prov_get_name,
1020 &mshv2prov_get_settings,
1021
1022 &mshv2prov_list_sandbox_ids,
1023 &mshv2prov_get_sandbox
1024 };
1025 vtbl = v;
1026 }
1027 return &vtbl;
1028 }
1029
1030 static gate_result_t mshv2prov_create(gate_string_t const* host, gate_virtualization_provider_t** ptr)
1031 {
1032 gate_result_t ret;
1033 mshv2prov_t* mshv2prov = NULL;
1034
1035 do
1036 {
1037 mshv2prov = (mshv2prov_t*)gate_mem_alloc(sizeof(mshv2prov_t));
1038 if (NULL == mshv2prov)
1039 {
1040 ret = GATE_RESULT_OUTOFMEMORY;
1041 break;
1042 }
1043 gate_mem_clear(mshv2prov, sizeof(mshv2prov_t));
1044 mshv2prov->vtbl = init_virutalization_provider_vtbl();
1045 gate_atomic_int_init(&mshv2prov->ref_counter, 1);
1046
1047 if (gate_string_is_empty(host))
1048 {
1049 host = &wmi_default_host;
1050 }
1051
1052 ret = gate_management_open(host, NULL, &wmi_default_namespace, 0, &mshv2prov->mgmt);
1053 GATE_BREAK_IF_FAILED(ret);
1054
1055 if (ptr != NULL)
1056 {
1057 *ptr = (gate_virtualization_provider_t*)mshv2prov;
1058 mshv2prov = NULL;
1059 }
1060 ret = GATE_RESULT_OK;
1061 } while (0);
1062
1063 if (NULL != mshv2prov)
1064 {
1065 gate_mem_dealloc(mshv2prov);
1066 }
1067 return ret;
1068 }
1069
1070 #endif /* GATE_TECH_VIRTUALIZATION_HYPERV2 */
1071
1072
1073
1074 #if defined(GATE_TECH_VIRTUALIZATION_WSL)
1075
1076 #include "gate/tech/platform/gate_wsl.h"
1077
1078 static gate_string_t const virtprov_name_wsl = GATE_STRING_INIT_STATIC("wsl");
1079 static gate_string_t const virtprov_descr_wsl = GATE_STRING_INIT_STATIC("Windows Subsystem for Linux");
1080
1081 typedef struct wsl_virtualization_provider_class
1082 {
1083 GATE_INTERFACE_VTBL(gate_virtualization_provider) const* vtbl;
1084
1085 gate_atomic_int_t ref_counter;
1086 } wsl_virtualization_provider_t;
1087
1088 static char const* wsl_get_interface_name(void* thisptr)
1089 {
1090 GATE_UNUSED_ARG(thisptr);
1091 return GATE_INTERFACE_NAME_VIRTUALIZATION_PROVIDER;
1092 }
1093 static void wsl_destroy(wsl_virtualization_provider_t* self)
1094 {
1095 gate_mem_dealloc(self);
1096 }
1097 static void wsl_release(void* thisptr)
1098 {
1099 wsl_virtualization_provider_t* self = (wsl_virtualization_provider_t*)thisptr;
1100 if (gate_atomic_int_dec(&self->ref_counter) == 0)
1101 {
1102 wsl_destroy(self);
1103 }
1104 }
1105 static int wsl_retain(void* thisptr)
1106 {
1107 wsl_virtualization_provider_t* self = (wsl_virtualization_provider_t*)thisptr;
1108 return gate_atomic_int_inc(&self->ref_counter);
1109 }
1110
1111 static gate_result_t wsl_get_name(void* thisptr, gate_string_t* name)
1112 {
1113 wsl_virtualization_provider_t* self = (wsl_virtualization_provider_t*)thisptr;
1114 gate_string_duplicate(name, &virtprov_name_wsl);
1115 return GATE_RESULT_OK;
1116 }
1117 static gate_result_t wsl_get_settings(void* thisptr, gate_property_t* settings)
1118 {
1119 wsl_virtualization_provider_t* self = (wsl_virtualization_provider_t*)thisptr;
1120 gate_property_create_empty(settings);
1121 return GATE_RESULT_OK;
1122 }
1123 static gate_result_t wsl_list_sandbox_ids(void* thisptr, gate_array_t* sandbox_ids)
1124 {
1125 wsl_virtualization_provider_t* self = (wsl_virtualization_provider_t*)thisptr;
1126 /* TODO */
1127 /* HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss */
1128 return GATE_RESULT_NOTIMPLEMENTED;
1129 }
1130 static gate_result_t wsl_get_sandbox(void* thisptr, gate_string_t const* sandbox_id, gate_virtualization_sandbox_t** ptr_sandbox)
1131 {
1132 wsl_virtualization_provider_t* self = (wsl_virtualization_provider_t*)thisptr;
1133 /* TODO */
1134 return GATE_RESULT_NOTIMPLEMENTED;
1135 }
1136
1137 static GATE_INTERFACE_VTBL(gate_virtualization_provider) const* wsl_provider_vtbl_init()
1138 {
1139 static GATE_INTERFACE_VTBL(gate_virtualization_provider) vtbl;
1140 if (vtbl.get_interface_name == NULL)
1141 {
1142 GATE_INTERFACE_VTBL(gate_virtualization_provider) v = {
1143 &wsl_get_interface_name,
1144 &wsl_release,
1145 &wsl_retain,
1146
1147 &wsl_get_name,
1148 &wsl_get_settings,
1149 &wsl_list_sandbox_ids,
1150 &wsl_get_sandbox
1151 };
1152 vtbl = v;
1153 }
1154 return &vtbl;
1155 }
1156
1157 static gate_result_t wsl_provider_create(gate_virtualization_provider_t** ptr_provider)
1158 {
1159 gate_result_t ret = GATE_RESULT_FAILED;
1160 wsl_virtualization_provider_t* wsl_prov = NULL;
1161 do
1162 {
1163 GATE_INTERFACE_VTBL(gate_virtualization_provider) const* vtbl = wsl_provider_vtbl_init();
1164 wsl_api_t* wsl = load_wsl_functions();
1165
1166 if (wsl == NULL)
1167 {
1168 ret = GATE_RESULT_NOTAVAILABLE;
1169 }
1170
1171 wsl_prov = (wsl_virtualization_provider_t*)gate_mem_alloc(sizeof(wsl_virtualization_provider_t));
1172 if (wsl_prov == NULL)
1173 {
1174 ret = GATE_RESULT_OUTOFMEMORY;
1175 break;
1176 }
1177
1178 wsl_prov->vtbl = vtbl;
1179 gate_atomic_int_init(&wsl_prov->ref_counter, 1);
1180
1181 /* success case reached: */
1182 *ptr_provider = (gate_virtualization_provider_t*)wsl_prov;
1183 wsl_prov = NULL;
1184 ret = GATE_RESULT_OK;
1185 } while (0);
1186
1187 if (wsl_prov)
1188 {
1189 wsl_release(wsl_prov);
1190 }
1191 return ret;
1192 }
1193
1194 #endif /* GATE_TECH_VIRTUALIZATION_WSL */
1195
1196
1197
1198 1 gate_result_t gate_tech_virtualization_providers_enum(gate_tech_virtualization_providers_callback_t callback, void* param)
1199 {
1200 1 gate_result_t ret = GATE_RESULT_OK;
1201
1202 do
1203 {
1204 #if defined(GATE_TECH_VIRTUALIZATION_LXC)
1205 /* lxc support */
1206
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (GATE_SUCCEEDED(gate_lxc_init()))
1207 {
1208 if (!callback(&virtprov_name_lxc, &virtprov_descr_lxc, param))
1209 {
1210 break;
1211 }
1212 }
1213 #endif /* GATE_TECH_VIRTUALIZATION_LXC */
1214
1215 #if defined(GATE_TECH_VIRTUALIZATION_HYPERV2)
1216 /* MS hyper-v wmi access */
1217 if (!callback(&virtprov_name_hyperv2, &virtprov_descr_hyperv2, param))
1218 {
1219 break;
1220 }
1221 #endif /* GATE_TECH_VIRTUALIZATION_HYPERV2 */
1222
1223 #if defined(GATE_TECH_VIRTUALIZATION_WSL)
1224 if (!callback(&virtprov_name_wsl, &virtprov_descr_wsl, param))
1225 {
1226 break;
1227 }
1228 #endif /* GATE_TECH_VIRTUALIZATION_WSL */
1229
1230 #if defined(GATE_TECH_VIRTUALIZATION_DOCKER)
1231 /* docker support */
1232
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!callback(&virtprov_name_docker, &virtprov_descr_docker, param))
1233 {
1234 break;
1235 }
1236 #endif /* GATE_TECH_VIRTUALIZATION_DOCKER */
1237
1238 } while (0);
1239
1240 1 return ret;
1241 }
1242
1243
1244 1 gate_result_t gate_tech_virtualization_provider_create(gate_string_t const* name, gate_virtualization_provider_t** ptr_provider)
1245 {
1246 1 gate_result_t ret = GATE_RESULT_NOMATCH;
1247
1248 do
1249 {
1250 #if defined(GATE_TECH_VIRTUALIZATION_LXC)
1251
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_string_equals(name, &virtprov_name_lxc))
1252 {
1253 ret = gate_lxc_init();
1254 GATE_BREAK_IF_FAILED(ret);
1255
1256 if (ptr_provider)
1257 {
1258 gate_virtualization_provider_t* prov = init_global_lxc_provider();
1259 if (!prov)
1260 {
1261 ret = GATE_RESULT_FAILED;
1262 break;
1263 }
1264 *ptr_provider = prov;
1265 }
1266 ret = GATE_RESULT_OK;
1267 break;
1268 }
1269 #endif /* GATE_TECH_VIRTUALIZATION_LXC */
1270
1271 #if defined(GATE_TECH_VIRTUALIZATION_HYPERV2)
1272 if (gate_string_equals(name, &virtprov_name_hyperv2))
1273 {
1274 ret = mshv2prov_create(NULL, ptr_provider);
1275 return ret;
1276 }
1277 #endif /* GATE_TECH_VIRTUALIZATION_HYPERV2 */
1278
1279 #if defined(GATE_TECH_VIRTUALIZATION_WSL)
1280 if (gate_string_equals(name, &virtprov_name_wsl))
1281 {
1282 ret = wsl_provider_create(ptr_provider);
1283 return ret;
1284 }
1285 #endif /* GATE_TECH_VIRTUALIZATION_WSL */
1286
1287 #if defined(GATE_TECH_VIRTUALIZATION_DOCKER)
1288
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_equals(name, &virtprov_name_docker))
1289 {
1290 /* TODO */
1291 1 ret = GATE_RESULT_FAILED;
1292 1 break;
1293 }
1294 #endif /* GATE_TECH_VIRTUALIZATION_DOCKER */
1295
1296 ret = GATE_RESULT_NOMATCH;
1297 } while (0);
1298
1299 1 return ret;
1300 }
1301