Wrapper: send/recv socket fd - based on public domain code
[platform/core/security/vasum.git] / wrapper / wrapper.cpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Krzysztof Dynowski <k.dynowski@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19
20 /**
21  * @file
22  * @author  Krzysztof Dynowski (k.dynowski@samsung.com)
23  * @brief   Vasum old API wrapper to slp client lib
24  */
25
26 #define __VASUM_WRAPPER_SOURCE__
27 #include <vector>
28 #include <string.h>
29 #include <algorithm>
30
31 #include "config.hpp"
32 #include "vasum-client-impl.hpp"
33 #include "logger/logger.hpp"
34 #include "logger/backend-journal.hpp"
35
36 #include "wrapper-compatibility.h"
37
38 struct WrappedZone
39 {
40     Client *client;
41     VsmZone zone;
42     struct vsm_zone vz;
43     std::vector<vsm_netdev> netdevs;
44 };
45
46 struct WrappedContext
47 {
48     Client *client;
49     vsm_context hq_ctx;
50     struct vsm_zone hq_root;
51     std::vector<WrappedZone> zones;
52 };
53
54 static struct
55 {
56     int done;
57 } wrap;
58
59
60 #ifndef offsetof
61 #define offsetof(type, memb) ((size_t)&((type *)0)->memb)
62 #endif
63 #ifdef container_of
64 #undef container_of
65 #endif
66 #ifndef container_of
67 #define container_of(ptr, type, memb) (\
68     (type *)((char *)(ptr) - offsetof(type, memb)))
69 #endif
70
71 #define UNUSED(x) ((void)(x))
72
73 #define vsm_attach_command_t vsm_attach_command_s
74 #define vsm_attach_options_t vsm_attach_options_s
75
76 void __attribute__ ((constructor)) wrapper_load(void);
77 void __attribute__ ((destructor)) wrapper_unload(void);
78 static void init_wrapper();
79 extern struct vasum_ops dummy_ops;
80
81 using namespace logger;
82 void wrapper_load(void)
83 {
84     Logger::setLogLevel(LogLevel::TRACE);
85     Logger::setLogBackend(new SystemdJournalBackend());
86     LOGI("wrapper_load");
87     init_wrapper();
88 }
89
90 void wrapper_unload(void)
91 {
92     LOGI("wrapper_unload");
93 }
94
95 static void callcheck()
96 {
97     init_wrapper();
98 }
99
100 void init_wrapper()
101 {
102     if (wrap.done) return ;
103     memset(&wrap, 0, sizeof(wrap));
104     wrap.done = 1;
105     LOGS("");
106 }
107
108 static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, VsmZone zone, bool create = false)
109 {
110     if (zone == NULL) {
111         return NULL;
112     }
113     for (auto& zw : w->zones) {
114         if (zw.zone == zone) {
115             return &zw.vz;
116         }
117     }
118     if (create) {
119         w->zones.push_back(WrappedZone());
120         WrappedZone& zw = w->zones.back();
121         zw.client = w->client;
122         zw.zone = zone;
123         zw.vz.name = zone->id;
124         zw.vz.id = 0;
125         zw.vz.type = NULL;
126         zw.vz.user_data = NULL;
127         zw.vz.rootfs_path = zone->rootfs_path;
128         zw.vz.parent = &zw.vz;
129         LOGI("return (create) zone " << zone->id);
130         return &w->zones.back().vz;
131     }
132     LOGE("return zone NULL");
133     return NULL;
134 }
135
136 static int wrap_error(VsmStatus st, const Client *c)
137 {
138     if (st == VSMCLIENT_SUCCESS) LOGI("return success " << st);
139     else LOGE("return error=" << st << ", msg=" << (c ? c->vsm_get_status_message() : "n/a"));
140     switch (st) {
141         case VSMCLIENT_SUCCESS: return VSM_ERROR_NONE;
142         case VSMCLIENT_CUSTOM_ERROR: return -VSM_ERROR_GENERIC;
143         case VSMCLIENT_IO_ERROR: return -VSM_ERROR_IO;
144         case VSMCLIENT_OPERATION_FAILED: return -VSM_ERROR_NOT_PERMITTED;
145         case VSMCLIENT_INVALID_ARGUMENT: return -VSM_ERROR_INVALID;
146         case VSMCLIENT_OTHER_ERROR: return -VSM_ERROR_GENERIC;
147     }
148     return -VSM_ERROR_GENERIC;
149 }
150
151 static void init_context_wrap(WrappedContext *w)
152 {
153     w->client = new Client();
154     VsmStatus st = w->client->connectSystem();
155     wrap_error(st, w->client);
156
157     memset(&w->hq_ctx, 0, sizeof(w->hq_ctx));
158     memset(&w->hq_root, 0, sizeof(w->hq_root));
159
160     vsm_context *ctx = &w->hq_ctx;
161     adt_init_list(&ctx->listeners);
162     //init root_zone
163     ctx->root_zone = &w->hq_root;
164     ctx->root_zone->name = (char*)"";
165     ctx->root_zone->id = 0;
166     ctx->root_zone->rootfs_path = (char*)"/";
167
168     ctx->root_zone->terminal = -1;
169     ctx->root_zone->state = VSM_ZONE_STATE_RUNNING;
170     ctx->root_zone->user_data = ctx->root_zone;
171
172     ctx->root_zone->parent = ctx->root_zone;
173     ctx->root_zone->ctx = ctx;
174
175     pthread_rwlock_init(&ctx->root_zone->lock, NULL);
176     adt_init_list(&ctx->root_zone->netdevs);
177     adt_init_list(&ctx->root_zone->devices);
178     adt_init_list(&ctx->root_zone->children);
179
180     pthread_rwlock_init(&ctx->lock, NULL);
181     adt_init_list(&ctx->listeners);
182     adt_init_list(&ctx->sc_listeners);
183     adt_init_list(&ctx->ev_listeners);
184
185     //struct mainloop *mainloop = mainloop_create();
186     //struct mxe_engine *engine = mxe_prepare_engine(mainloop, ctx);
187     //struct mxe_endpoint *ep = mxe_create_client(engine, SERVICEPATH);
188
189     ctx->foreground_zone = ctx->root_zone;
190     ctx->vsm_ops = &dummy_ops;
191     ctx->error = VSM_ERROR_NONE;
192     //ctx->data = ep;
193 }
194
195 extern "C" {
196 API void vsm_string_free(VsmString string);
197 API void vsm_array_string_free(VsmArrayString astring);
198
199 API vsm_context_h vsm_create_context(void)
200 {
201     LOGS("");
202     callcheck();
203     WrappedContext *w = new WrappedContext();
204     init_context_wrap(w);
205
206     vsm_context *ctx = &w->hq_ctx;
207     return ctx;
208 }
209
210 API int vsm_cleanup_context(vsm_context_h ctx)
211 {
212     LOGS("");
213     callcheck();
214     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
215     if (w->client != NULL) {
216         delete w->client;
217         w->client = NULL;
218     }
219     for (auto& zw : w->zones) {
220         zw.netdevs.clear();
221     }
222     w->zones.clear();
223     pthread_rwlock_destroy(&ctx->lock);
224     delete w;
225     return VSM_ERROR_NONE;
226 }
227
228 static const char *const vsm_error_strtab[] = {
229     "No error",
230     "Undefined error",
231     "Invalid",
232     "Operation cancelled",
233     "Operation aborted",
234     "Connection refused",
235     "Object exists",
236     "Resource busy",
237     "Input/Output error",
238     "Timeout",
239     "Overflow",
240     "Out of memory",
241     "Out of range",
242     "Operation not permitted",
243     "Function not implemented",
244     "Operation not supported",
245     "Access denied",
246     "No object found",
247     "Bad state"
248 };
249
250 API vsm_error_e vsm_last_error(struct vsm_context *ctx)
251 {
252     if (ctx)
253         return ctx->error;
254     return static_cast<vsm_error_e>(-1);
255 }
256
257 API int vsm_get_poll_fd(struct vsm_context *ctx)
258 {
259     LOGS("");
260     callcheck();
261     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
262     UNUSED(w);
263     //FIXME Client should create Dispatcher and pass to IPCConnection
264     //      now: IPCConnection has field ThreadWrapper
265     //return w->client->getEventPoll().getPollFD();
266     return -1;
267 }
268 API int vsm_enter_eventloop(struct vsm_context *ctx, int flags, int timeout)
269 {
270     LOGS("");
271     callcheck();
272     UNUSED(flags);
273     UNUSED(timeout);
274     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
275     UNUSED(w);
276     //FIXME Client should create Dispatcher and pass to IPCConnection
277     //      now: IPCConnection has field ThreadWrapper
278     //TODO Use EventPoll from Dispatcher
279     return 0;
280 }
281
282 API int vsm_create_zone(struct vsm_context *ctx, const char *zone_name, const char *template_name, int flag)
283 {
284     LOGS("create_zone " << zone_name);
285     callcheck();
286     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
287     UNUSED(flag);
288     //template_name = NULL; //template name not supported by libvasum-client
289     if (!w->client) return VSM_ERROR_GENERIC;
290     VsmStatus st = w->client->vsm_create_zone(zone_name, template_name);
291     if (st != VSMCLIENT_SUCCESS) {
292         LOGE("vsm_create_zone(" << zone_name << ") = " << st);
293     }
294     return wrap_error(st, w->client);
295 }
296
297 API int vsm_destroy_zone(struct vsm_context *ctx, const char *zone_name, int force)
298 {
299     LOGS("zone=" << zone_name);
300     callcheck();
301     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
302     UNUSED(force);
303     if (!w->client) return VSM_ERROR_GENERIC;
304     VsmStatus st = w->client->vsm_destroy_zone(zone_name);
305     if (st == VSMCLIENT_SUCCESS) {
306         auto zonebyname = [zone_name](const WrappedZone& v) {return v.zone->id == zone_name;};
307         auto zonelist = std::remove_if(w->zones.begin(), w->zones.end(), zonebyname);
308         w->zones.erase(zonelist);
309     }
310     return wrap_error(st, w->client);
311 }
312
313 API int vsm_start_zone(struct vsm_context *ctx, const char *zone_name)
314 {
315     LOGS("zone=" << zone_name);
316     callcheck();
317     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
318     if (!w->client) return VSM_ERROR_GENERIC;
319     VsmStatus st = w->client->vsm_start_zone(zone_name);
320     return wrap_error(st, w->client);
321 }
322
323 API int vsm_shutdown_zone(struct vsm_context *ctx, const char *zone_name, int force)
324 {
325     LOGS("zone=" << zone_name);
326     callcheck();
327     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
328     UNUSED(force);
329     if (!w->client) return VSM_ERROR_GENERIC;
330     VsmStatus st = w->client->vsm_shutdown_zone(zone_name);
331     return wrap_error(st, w->client);
332 }
333
334 API int vsm_lock_zone(struct vsm_context *ctx, const char *zone_name, int shutdown)
335 {
336     LOGS("zone=" << zone_name);
337     callcheck();
338     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
339     UNUSED(shutdown);
340     if (!w->client) return VSM_ERROR_GENERIC;
341     VsmStatus st = w->client->vsm_lock_zone(zone_name);
342     return wrap_error(st, w->client);
343 }
344
345 API int vsm_unlock_zone(struct vsm_context *ctx, const char *zone_name)
346 {
347     LOGS("zone=" << zone_name);
348     callcheck();
349     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
350     if (!w->client) return VSM_ERROR_GENERIC;
351     VsmStatus st = w->client->vsm_lock_zone(zone_name);
352     return wrap_error(st, w->client);
353 }
354
355 API int vsm_set_foreground(struct vsm_zone *zone)
356 {
357     LOGS("");
358     callcheck();
359     WrappedZone *w = container_of(zone, WrappedZone, vz);
360     if (!w->client) return VSM_ERROR_GENERIC;
361     VsmStatus st = w->client->vsm_set_active_zone(zone->name);
362     return wrap_error(st, w->client);
363 }
364
365 //execute command in specified zone
366 API int vsm_attach_zone(struct vsm_context *ctx,
367                         const char *zone_name,
368                         vsm_attach_command_t *command,
369                         vsm_attach_options_t *opts,
370                         pid_t *attached_process)
371 {
372     return dummy_ops.attach_zone(ctx, zone_name, command, opts,
373                      attached_process);
374 }
375
376 //execute command in specified zone and wait
377 API int vsm_attach_zone_wait(struct vsm_context *ctx,
378                              const char *zone_name,
379                              vsm_attach_command_t *command,
380                              vsm_attach_options_t *opts)
381 {
382     return dummy_ops.attach_zone_wait(ctx, zone_name, command, opts);
383 }
384
385 API int vsm_iterate_zone(struct vsm_context *ctx, void (*callback)(struct vsm_zone *zone, void *user_data), void *user_data)
386 {
387     LOGS("");
388     callcheck();
389     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
390     if (!w->client) return -VSM_ERROR_GENERIC;
391     callback(ctx->root_zone, user_data);
392     for (auto& z : w->zones) {
393         LOGI("iterate callback zone: " << z.zone->id);
394         callback(&z.vz, user_data);
395     }
396     return 0;
397 }
398
399 API struct vsm_zone *vsm_lookup_zone_by_name(struct vsm_context *ctx, const char *path)
400 {
401     LOGS("name=" << path);
402     callcheck();
403     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
404     VsmZone zone;
405     if (!w->client) return NULL;
406     //CHECK if path is same as zone_name
407     if (w->client->vsm_lookup_zone_by_id(path, &zone) != VSMCLIENT_SUCCESS)
408         return NULL;
409     return wrap_vsm_zone(w, zone, true);
410 }
411
412 //supposed return ref to internal struct
413 API struct vsm_zone *vsm_lookup_zone_by_pid(struct vsm_context *ctx, pid_t pid)
414 {
415     LOGS("pid=" << pid);
416     callcheck();
417     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
418     VsmZone zone;
419     VsmString id;
420     VsmStatus st;
421     if (!w->client) return NULL;
422     if ((st = w->client->vsm_lookup_zone_by_pid(pid, &id)) != VSMCLIENT_SUCCESS) {
423         wrap_error(st, w->client);
424         return NULL;
425     }
426     LOGI("found zone(pid=" << pid << ")='" << id << "'");
427     if (::strcmp(id, "host") == 0) {
428         return w->hq_ctx.root_zone;
429     }
430     w->client->vsm_lookup_zone_by_id(id, &zone); //zone is malloced
431     return wrap_vsm_zone(w, zone);
432 }
433
434 API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_changed_cb callback, void *user_data)
435 {
436     LOGS("");
437     callcheck();
438     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
439     VsmSubscriptionId subscriptionId;
440
441     auto dbus_cb = [=](const char* id, const char* dbusAddress, void* data) ->
442     void {
443         VsmZone zone;
444         //TODO what are valid state, event
445         vsm_zone_state_t t = VSM_ZONE_STATE_RUNNING;
446         UNUSED(dbusAddress);
447         w->client->vsm_lookup_zone_by_id(id, &zone);
448         callback(wrap_vsm_zone(w, zone), t, data);
449     };
450     w->client->vsm_add_state_callback(dbus_cb, user_data, &subscriptionId);
451     return (int)subscriptionId;
452 }
453
454 API int vsm_del_state_changed_callback(struct vsm_context *ctx, int handle)
455 {
456     LOGS("");
457     callcheck();
458     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
459     VsmSubscriptionId subscriptionId = (VsmSubscriptionId)handle;
460     VsmStatus st = w->client->vsm_del_state_callback(subscriptionId);
461     return wrap_error(st, w->client);
462 }
463
464 API int vsm_grant_device(struct vsm_zone *dom, const char *name, uint32_t flags)
465 {
466     LOGS("");
467     callcheck();
468     WrappedZone *w = container_of(dom, WrappedZone, vz);
469     const char *id = dom->name;
470     VsmZone zone;
471     w->client->vsm_lookup_zone_by_id(id, &zone);
472     VsmStatus st = w->client->vsm_grant_device(id, name, flags);
473     return wrap_error(st, w->client);
474 }
475
476 API int vsm_revoke_device(struct vsm_zone *dom, const char *name)
477 {
478     LOGS("");
479     callcheck();
480     WrappedZone *w = container_of(dom, WrappedZone, vz);
481     const char *id = dom->name;
482     VsmStatus st = w->client->vsm_revoke_device(id, name);
483     return wrap_error(st, w->client);
484 }
485
486 API struct vsm_netdev *vsm_create_netdev(struct vsm_zone *zone, vsm_netdev_type_t type, const char *target, const char *netdev)
487 {
488     LOGS("");
489     callcheck();
490     UNUSED(zone);
491     UNUSED(type);
492     UNUSED(target);
493     UNUSED(netdev);
494
495     WrappedZone *w = container_of(zone, WrappedZone, vz);
496     const char *id = zone->name;
497     VsmStatus st;
498     if (type == VSM_NETDEV_VETH)
499         st = w->client->vsm_create_netdev_veth(id, target, netdev);
500     else if (type == VSM_NETDEV_PHYS)
501         st = w->client->vsm_create_netdev_phys(id, netdev);
502     else if (type == VSM_NETDEV_MACVLAN) // macvlan_mode from if_link.h
503         st = w->client->vsm_create_netdev_macvlan(id, target, netdev, MACVLAN_MODE_BRIDGE);
504     else {
505         LOGE("Invalid arguments");
506         //ctx->error = VSM_ERROR_INVALID;
507         return NULL;
508     }
509
510     if (st != VSMCLIENT_SUCCESS) {
511         LOGE("vsm_create_netdev(" << netdev << ") = " << st);
512         return NULL;
513     }
514
515     vsm_netdev vnd;
516     vnd.zone = zone;
517     vnd.name = (char*)netdev; //FIXME? copy content of string
518     vnd.type = type;
519     w->netdevs.push_back(vnd); //copy pushed to vector
520     return &w->netdevs.back(); //pointer to struct on vector
521 }
522
523 API int vsm_destroy_netdev(vsm_netdev_h)
524 {
525     LOGS("");
526     return 0;
527 }
528
529 API int vsm_iterate_netdev(struct vsm_zone *zone, void (*callback)(struct vsm_netdev *, void *user_data), void *user_data)
530 {
531     LOGS("");
532     callcheck();
533     WrappedZone *w = container_of(zone, WrappedZone, vz);
534     for (auto nd : w->netdevs) {
535         callback(&nd, user_data);
536     }
537     return 0;
538 }
539
540 API struct vsm_netdev *vsm_lookup_netdev_by_name(struct vsm_zone *zone, const char *name)
541 {
542     LOGS("");
543     callcheck();
544     WrappedZone *w = container_of(zone, WrappedZone, vz);
545     VsmNetdev nd;
546     VsmStatus st = w->client->vsm_lookup_netdev_by_name(zone->name, name, &nd);
547     if (st == VSMCLIENT_SUCCESS) {
548         auto devbyname = [name](const vsm_netdev& v) {return ::strcmp(v.name, name) == 0;};
549         auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname);
550         if (devlist != w->netdevs.end()) {
551             return &devlist[0];
552         }
553     }
554     return NULL;
555 }
556
557 API int vsm_declare_file(struct vsm_context *ctx, vsm_fso_type_t ftype, const char *path, int flags, vsm_mode_t mode)
558 {
559     LOGS("");
560     callcheck();
561 /*  Old implementation is following: (but implemented in server)
562     args.oldpath = oldpath;
563     args.newpath = newpath;
564     ret = iterate_running_zone("/sys/fs/cgroup/cpuset/lxc", file_resource, &args);
565 */
566     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
567     VsmArrayString ids = NULL;
568     VsmFileType type;
569     switch (ftype) {
570         case VSM_FSO_TYPE_DIR:  /**< Directoy type */
571             type = VSMFILE_DIRECTORY;
572             break;
573         case VSM_FSO_TYPE_REG:  /**< Regular file type */
574             type = VSMFILE_REGULAR;
575             break;
576         case VSM_FSO_TYPE_FIFO: /**< Fifo file type */
577             type = VSMFILE_FIFO;
578             break;
579         case VSM_FSO_TYPE_SOCK: /**< Socket file type */
580             return VSM_ERROR_NONE;
581         case VSM_FSO_TYPE_DEV:  /**< Device node type */
582             return VSM_ERROR_NONE;
583         default:
584             return VSM_ERROR_NONE;
585     }
586     w->client->vsm_get_zone_ids(&ids);
587     if (ids != NULL) {
588         for (VsmString* id = ids; *id; ++id) {
589             VsmStatus st = w->client->vsm_declare_file(*id, type, path, (int32_t)flags, (mode_t)mode, NULL);
590             if (st != VSMCLIENT_SUCCESS) {
591                 wrap_error(st, w->client);
592             }
593         }
594     }
595     vsm_array_string_free(ids);
596     return VSM_ERROR_NONE;
597 }
598
599 API int vsm_declare_link(struct vsm_context *ctx, const char *source, const char *target)
600 {
601     LOGS("src=" << source << ", dst=" << target);
602     callcheck();
603 /*  Old implementation is following: (but implemented in server)
604     args.oldpath = oldpath;
605     args.newpath = newpath;
606     ret = iterate_running_zone("/sys/fs/cgroup/cpuset/lxc", link_resource, &args);
607 */
608     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
609     VsmArrayString ids = NULL;
610     w->client->vsm_get_zone_ids(&ids);
611     if (ids != NULL)
612     for (VsmString* id = ids; *id; ++id) {
613         VsmStatus st = w->client->vsm_declare_link(source, *id, target, NULL);
614         if (st != VSMCLIENT_SUCCESS)
615             wrap_error(st, w->client);
616     }
617     vsm_array_string_free(ids);
618     return VSM_ERROR_NONE;
619 }
620
621 API int vsm_declare_mount(struct vsm_context *ctx,
622                           const char *source,
623                           const char *target,
624                           const char *fstype,
625                           unsigned long flags,
626                           const void *data)
627 {
628     LOGS("");
629     callcheck();
630 /*  Old implementation is following: (but implemented in server)
631     args.oldpath = oldpath;
632     args.newpath = newpath;
633     ret = iterate_running_zone("/sys/fs/cgroup/cpuset/lxc", mount_resource, &args);
634 */
635     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
636     VsmArrayString ids = NULL;
637     w->client->vsm_get_zone_ids(&ids);
638     if (ids != NULL) {
639         for (VsmString* id = ids; *id; ++id) {
640             VsmStatus st = w->client->vsm_declare_mount(source, *id, target, fstype, flags, (const char *)data, NULL);
641             if (st != VSMCLIENT_SUCCESS) {
642                 wrap_error(st, w->client);
643             }
644         }
645     }
646     vsm_array_string_free(ids);
647     return VSM_ERROR_NONE;
648 }
649
650 API const char * vsm_get_zone_rootpath(vsm_zone_h  zone)
651 {
652     LOGS("");
653     return zone == NULL ? NULL : zone->rootfs_path;
654 }
655 API const char * vsm_get_zone_name(vsm_zone_h zone)
656 {
657     LOGS("");
658     return zone == NULL ? NULL : zone->name;
659 }
660 API int vsm_is_host_zone(vsm_zone_h zone)
661 {
662     LOGS("");
663     if (zone == NULL)
664         return -VSM_ERROR_INVALID;
665
666     LOGI("zone->parent == zone is " << (zone->parent == zone ? 1 : 0));
667     return zone->parent == zone ? 1 : 0;
668 }
669 API vsm_zone_h vsm_join_zone(vsm_zone_h  /*zone*/)
670 {
671     LOGS("");
672     return NULL;
673 }
674 API int vsm_canonicalize_path(const char *input_path, char **output_path)
675 {
676     LOGS(""<<input_path);
677     *output_path = strdup(input_path);
678     int len = strlen(input_path);
679     return len;
680 }
681
682 // Note: support the newer API (incomaptible with older)
683 API const char *vsm_error_string(vsm_error_e error)
684 {
685     LOGS("");
686     callcheck();
687     if (error < 0 || error > VSM_MAX_ERROR) {
688         return NULL;
689     }
690     return vsm_error_strtab[error];
691 }
692
693 API struct vsm_zone *vsm_lookup_zone_by_terminal_id(struct vsm_context *ctx, int terminal)
694 {
695     LOGS("terminal=" << terminal);
696     callcheck();
697     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
698     VsmZone zone;
699     VsmString id;
700     if (!w->client) return NULL;
701     if (w->client->vsm_lookup_zone_by_terminal_id(terminal, &id) != VSMCLIENT_SUCCESS)
702         return NULL;
703     w->client->vsm_lookup_zone_by_id(id, &zone);
704     return wrap_vsm_zone(w, zone);
705 }
706
707 API void vsm_array_string_free(VsmArrayString astring)
708 {
709     if (!astring) {
710         return;
711     }
712     for (char** ptr = astring; *ptr; ++ptr) {
713         vsm_string_free(*ptr);
714     }
715     free(astring);
716 }
717
718 API void vsm_string_free(VsmString string)
719 {
720     free(string);
721 }
722
723 API int vsm_add_event_callback(vsm_context_h, vsm_zone_event_cb, void*) {
724     LOGS("");
725     return 0;
726 }
727 API int vsm_del_event_callback(vsm_context_h, int) {
728     LOGS("");
729     return 0;
730 }
731 API int vsm_add_state_callback(vsm_context_h , vsm_zone_state_cb , void *) {
732     LOGS("");
733     return 0;
734 }
735 API int vsm_del_state_callback(vsm_context_h , int ) {
736     LOGS("");
737     return 0;
738 }
739 API int vsm_down_netdev(vsm_netdev_h) {
740     LOGS("");
741     return 0;
742 }
743 API vsm_zone* vsm_get_foreground(vsm_context_h ctx) {
744     LOGS("");
745     //return ((struct vasum_ops *)(ctx->vsm_ops))->get_foreground(ctx);
746     return dummy_ops.get_foreground(ctx);
747 }
748 API int vsm_get_host_pid(vsm_zone_h, pid_t) {
749     LOGS("");
750     return 0;
751 }
752 API int vsm_get_ip_addr_netdev(vsm_netdev_h, vsm_netdev_addr_t, char*, int) {
753     LOGS("");
754     return 0;
755 }
756 API void* vsm_get_userdata(vsm_zone_h) {
757     LOGS("");
758     return NULL;
759 }
760 API int vsm_get_zone_id(vsm_zone_h zone) {
761     LOGS("");
762     if (zone == NULL)
763         return -VSM_ERROR_INVALID;
764     return zone->id;
765 }
766 API vsm_zone_state_t vsm_get_zone_state(vsm_zone_h zone) {
767     LOGS("");
768     if (zone == NULL)
769         return static_cast<vsm_zone_state_t>(-VSM_ERROR_INVALID);
770     return zone->state;
771 }
772 API int vsm_get_zone_terminal(vsm_zone_h) {
773     LOGS("");
774     return -VSM_ERROR_NOT_SUPPORTED;
775 }
776 API const char *vsm_get_zone_type(vsm_zone_h zone) {
777     LOGS("");
778     return zone == NULL ? NULL : zone->type;
779 }
780 API int vsm_is_equivalent_zone(vsm_context_h, pid_t) {
781     LOGS("");
782     return 0;
783 }
784 API int vsm_is_virtualized() {
785     LOGS("");
786     return 0; /* Running in Host */
787 }
788 // libs/network.c
789 API int vsm_set_ip_addr_netdev(vsm_netdev_h, vsm_netdev_addr_t, const char*, int) {
790     LOGS("");
791     return 0;
792 }
793 API int vsm_up_netdev(vsm_netdev_h) {
794     LOGS("");
795     return 0;
796 }
797 // libs/zone.c
798 API int vsm_set_userdata(vsm_zone_h, void*) {
799     LOGS("");
800     return 0;
801 }
802 API int vsm_state_change_watch_callback(struct vsm_context * /*ctx*/, char * /*name*/,
803                     int  /*state*/, int  /*event*/) {
804     LOGS("");
805     return 0;
806 }
807 // libs/vsm_signal.c
808 API int vsm_signal_state_broadcast(struct mxe_engine * /*engine*/, const char * /*zone_name*/, int  /*state*/) {
809     LOGS("");
810     return 0;
811 }
812 API int vsm_signal_event_broadcast(struct mxe_engine * /*engine*/, const char * /*zone_name*/, int  /*event*/) {
813     LOGS("");
814     return 0;
815 }
816 } // extern "C"