logger: set thread id column width to 2
[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, Zone 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) {
307             return static_cast<Zone>(v.zone)->id == zone_name;
308         };
309         auto zonelist = std::remove_if(w->zones.begin(), w->zones.end(), zonebyname);
310         w->zones.erase(zonelist);
311     }
312     return wrap_error(st, w->client);
313 }
314
315 API int vsm_start_zone(struct vsm_context *ctx, const char *zone_name)
316 {
317     LOGS("zone=" << zone_name);
318     callcheck();
319     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
320     if (!w->client) return VSM_ERROR_GENERIC;
321     VsmStatus st = w->client->vsm_start_zone(zone_name);
322     return wrap_error(st, w->client);
323 }
324
325 API int vsm_shutdown_zone(struct vsm_context *ctx, const char *zone_name, int force)
326 {
327     LOGS("zone=" << zone_name);
328     callcheck();
329     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
330     UNUSED(force);
331     if (!w->client) return VSM_ERROR_GENERIC;
332     VsmStatus st = w->client->vsm_shutdown_zone(zone_name);
333     return wrap_error(st, w->client);
334 }
335
336 API int vsm_lock_zone(struct vsm_context *ctx, const char *zone_name, int shutdown)
337 {
338     LOGS("zone=" << zone_name);
339     callcheck();
340     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
341     UNUSED(shutdown);
342     if (!w->client) return VSM_ERROR_GENERIC;
343     VsmStatus st = w->client->vsm_lock_zone(zone_name);
344     return wrap_error(st, w->client);
345 }
346
347 API int vsm_unlock_zone(struct vsm_context *ctx, const char *zone_name)
348 {
349     LOGS("zone=" << zone_name);
350     callcheck();
351     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
352     if (!w->client) return VSM_ERROR_GENERIC;
353     VsmStatus st = w->client->vsm_lock_zone(zone_name);
354     return wrap_error(st, w->client);
355 }
356
357 API int vsm_set_foreground(struct vsm_zone *zone)
358 {
359     LOGS("");
360     callcheck();
361     WrappedZone *w = container_of(zone, WrappedZone, vz);
362     if (!w->client) return VSM_ERROR_GENERIC;
363     VsmStatus st = w->client->vsm_set_active_zone(zone->name);
364     return wrap_error(st, w->client);
365 }
366
367 //execute command in specified zone
368 API int vsm_attach_zone(struct vsm_context *ctx,
369                         const char *zone_name,
370                         vsm_attach_command_t *command,
371                         vsm_attach_options_t *opts,
372                         pid_t *attached_process)
373 {
374     return dummy_ops.attach_zone(ctx, zone_name, command, opts,
375                      attached_process);
376 }
377
378 //execute command in specified zone and wait
379 API int vsm_attach_zone_wait(struct vsm_context *ctx,
380                              const char *zone_name,
381                              vsm_attach_command_t *command,
382                              vsm_attach_options_t *opts)
383 {
384     return dummy_ops.attach_zone_wait(ctx, zone_name, command, opts);
385 }
386
387 API int vsm_iterate_zone(struct vsm_context *ctx, void (*callback)(struct vsm_zone *zone, void *user_data), void *user_data)
388 {
389     LOGS("");
390     callcheck();
391     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
392     if (!w->client) return -VSM_ERROR_GENERIC;
393     callback(ctx->root_zone, user_data);
394     for (auto& z : w->zones) {
395         LOGI("iterate callback zone: " << static_cast<Zone>(z.zone)->id);
396         callback(&z.vz, user_data);
397     }
398     return 0;
399 }
400
401 API struct vsm_zone *vsm_lookup_zone_by_name(struct vsm_context *ctx, const char *path)
402 {
403     LOGS("name=" << path);
404     callcheck();
405     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
406     Zone zone;
407     if (!w->client) return NULL;
408     //CHECK if path is same as zone_name
409     if (w->client->vsm_lookup_zone_by_id(path, &zone) != VSMCLIENT_SUCCESS)
410         return NULL;
411     return wrap_vsm_zone(w, zone, true);
412 }
413
414 //supposed return ref to internal struct
415 API struct vsm_zone *vsm_lookup_zone_by_pid(struct vsm_context *ctx, pid_t pid)
416 {
417     LOGS("pid=" << pid);
418     callcheck();
419     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
420     Zone zone;
421     VsmString id;
422     VsmStatus st;
423     if (!w->client) return NULL;
424     if ((st = w->client->vsm_lookup_zone_by_pid(pid, &id)) != VSMCLIENT_SUCCESS) {
425         wrap_error(st, w->client);
426         return NULL;
427     }
428     LOGI("found zone(pid=" << pid << ")='" << id << "'");
429     if (::strcmp(id, "host") == 0) {
430         return w->hq_ctx.root_zone;
431     }
432     w->client->vsm_lookup_zone_by_id(id, &zone); //zone is malloced
433     return wrap_vsm_zone(w, zone);
434 }
435
436 API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_changed_cb callback, void *user_data)
437 {
438     LOGS("");
439     callcheck();
440     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
441     VsmSubscriptionId subscriptionId;
442
443     auto dbus_cb = [=](const char* id, const char* dbusAddress, void* data) ->
444     void {
445         Zone zone;
446         //TODO what are valid state, event
447         vsm_zone_state_t t = VSM_ZONE_STATE_RUNNING;
448         UNUSED(dbusAddress);
449         w->client->vsm_lookup_zone_by_id(id, &zone);
450         callback(wrap_vsm_zone(w, zone), t, data);
451     };
452     w->client->vsm_add_state_callback(dbus_cb, user_data, &subscriptionId);
453     return (int)subscriptionId;
454 }
455
456 API int vsm_del_state_changed_callback(struct vsm_context *ctx, int handle)
457 {
458     LOGS("");
459     callcheck();
460     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
461     VsmSubscriptionId subscriptionId = (VsmSubscriptionId)handle;
462     VsmStatus st = w->client->vsm_del_state_callback(subscriptionId);
463     return wrap_error(st, w->client);
464 }
465
466 API int vsm_grant_device(struct vsm_zone *dom, const char *name, uint32_t flags)
467 {
468     LOGS("");
469     callcheck();
470     WrappedZone *w = container_of(dom, WrappedZone, vz);
471     const char *id = dom->name;
472     Zone zone;
473     w->client->vsm_lookup_zone_by_id(id, &zone);
474     VsmStatus st = w->client->vsm_grant_device(id, name, flags);
475     return wrap_error(st, w->client);
476 }
477
478 API int vsm_revoke_device(struct vsm_zone *dom, const char *name)
479 {
480     LOGS("");
481     callcheck();
482     WrappedZone *w = container_of(dom, WrappedZone, vz);
483     const char *id = dom->name;
484     VsmStatus st = w->client->vsm_revoke_device(id, name);
485     return wrap_error(st, w->client);
486 }
487
488 API struct vsm_netdev *vsm_create_netdev(struct vsm_zone *zone, vsm_netdev_type_t type, const char *target, const char *netdev)
489 {
490     LOGS("");
491     callcheck();
492     UNUSED(zone);
493     UNUSED(type);
494     UNUSED(target);
495     UNUSED(netdev);
496
497     WrappedZone *w = container_of(zone, WrappedZone, vz);
498     const char *id = zone->name;
499     VsmStatus st;
500     if (type == VSM_NETDEV_VETH)
501         st = w->client->vsm_create_netdev_veth(id, target, netdev);
502     else if (type == VSM_NETDEV_PHYS)
503         st = w->client->vsm_create_netdev_phys(id, netdev);
504     else if (type == VSM_NETDEV_MACVLAN) // macvlan_mode from if_link.h
505         st = w->client->vsm_create_netdev_macvlan(id, target, netdev, MACVLAN_MODE_BRIDGE);
506     else {
507         LOGE("Invalid arguments");
508         //ctx->error = VSM_ERROR_INVALID;
509         return NULL;
510     }
511
512     if (st != VSMCLIENT_SUCCESS) {
513         LOGE("vsm_create_netdev(" << netdev << ") = " << st);
514         return NULL;
515     }
516
517     vsm_netdev vnd;
518     vnd.zone = zone;
519     vnd.name = (char*)netdev; //FIXME? copy content of string
520     vnd.type = type;
521     w->netdevs.push_back(vnd); //copy pushed to vector
522     return &w->netdevs.back(); //pointer to struct on vector
523 }
524
525 API int vsm_destroy_netdev(vsm_netdev_h)
526 {
527     LOGS("");
528     return 0;
529 }
530
531 API int vsm_iterate_netdev(struct vsm_zone *zone, void (*callback)(struct vsm_netdev *, void *user_data), void *user_data)
532 {
533     LOGS("");
534     callcheck();
535     WrappedZone *w = container_of(zone, WrappedZone, vz);
536     for (auto nd : w->netdevs) {
537         callback(&nd, user_data);
538     }
539     return 0;
540 }
541
542 API struct vsm_netdev *vsm_lookup_netdev_by_name(struct vsm_zone *zone, const char *name)
543 {
544     LOGS("");
545     callcheck();
546     WrappedZone *w = container_of(zone, WrappedZone, vz);
547     Netdev nd;
548     VsmStatus st = w->client->vsm_lookup_netdev_by_name(zone->name, name, &nd);
549     if (st == VSMCLIENT_SUCCESS) {
550         auto devbyname = [name](const vsm_netdev& v) {return ::strcmp(v.name, name) == 0;};
551         auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname);
552         if (devlist != w->netdevs.end()) {
553             return &devlist[0];
554         }
555     }
556     return NULL;
557 }
558
559 API int vsm_declare_file(struct vsm_context *ctx, vsm_fso_type_t ftype, const char *path, int flags, vsm_mode_t mode)
560 {
561     LOGS("");
562     callcheck();
563 /*  Old implementation is following: (but implemented in server)
564     args.oldpath = oldpath;
565     args.newpath = newpath;
566     ret = iterate_running_zone("/sys/fs/cgroup/cpuset/lxc", file_resource, &args);
567 */
568     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
569     VsmArrayString ids = NULL;
570     VsmFileType type;
571     switch (ftype) {
572         case VSM_FSO_TYPE_DIR:  /**< Directoy type */
573             type = VSMFILE_DIRECTORY;
574             break;
575         case VSM_FSO_TYPE_REG:  /**< Regular file type */
576             type = VSMFILE_REGULAR;
577             break;
578         case VSM_FSO_TYPE_FIFO: /**< Fifo file type */
579             type = VSMFILE_FIFO;
580             break;
581         case VSM_FSO_TYPE_SOCK: /**< Socket file type */
582             return VSM_ERROR_NONE;
583         case VSM_FSO_TYPE_DEV:  /**< Device node type */
584             return VSM_ERROR_NONE;
585         default:
586             return VSM_ERROR_NONE;
587     }
588     w->client->vsm_get_zone_ids(&ids);
589     if (ids != NULL) {
590         for (VsmString* id = ids; *id; ++id) {
591             VsmStatus st = w->client->vsm_declare_file(*id, type, path, (int32_t)flags, (mode_t)mode, NULL);
592             if (st != VSMCLIENT_SUCCESS) {
593                 wrap_error(st, w->client);
594             }
595         }
596     }
597     vsm_array_string_free(ids);
598     return VSM_ERROR_NONE;
599 }
600
601 API int vsm_declare_link(struct vsm_context *ctx, const char *source, const char *target)
602 {
603     LOGS("src=" << source << ", dst=" << target);
604     callcheck();
605 /*  Old implementation is following: (but implemented in server)
606     args.oldpath = oldpath;
607     args.newpath = newpath;
608     ret = iterate_running_zone("/sys/fs/cgroup/cpuset/lxc", link_resource, &args);
609 */
610     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
611     VsmArrayString ids = NULL;
612     w->client->vsm_get_zone_ids(&ids);
613     if (ids != NULL)
614     for (VsmString* id = ids; *id; ++id) {
615         VsmStatus st = w->client->vsm_declare_link(source, *id, target, NULL);
616         if (st != VSMCLIENT_SUCCESS)
617             wrap_error(st, w->client);
618     }
619     vsm_array_string_free(ids);
620     return VSM_ERROR_NONE;
621 }
622
623 API int vsm_declare_mount(struct vsm_context *ctx,
624                           const char *source,
625                           const char *target,
626                           const char *fstype,
627                           unsigned long flags,
628                           const void *data)
629 {
630     LOGS("");
631     callcheck();
632 /*  Old implementation is following: (but implemented in server)
633     args.oldpath = oldpath;
634     args.newpath = newpath;
635     ret = iterate_running_zone("/sys/fs/cgroup/cpuset/lxc", mount_resource, &args);
636 */
637     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
638     VsmArrayString ids = NULL;
639     w->client->vsm_get_zone_ids(&ids);
640     if (ids != NULL) {
641         for (VsmString* id = ids; *id; ++id) {
642             VsmStatus st = w->client->vsm_declare_mount(source, *id, target, fstype, flags, (const char *)data, NULL);
643             if (st != VSMCLIENT_SUCCESS) {
644                 wrap_error(st, w->client);
645             }
646         }
647     }
648     vsm_array_string_free(ids);
649     return VSM_ERROR_NONE;
650 }
651
652 API const char * vsm_get_zone_rootpath(vsm_zone_h  zone)
653 {
654     LOGS("");
655     return zone == NULL ? NULL : zone->rootfs_path;
656 }
657 API const char * vsm_get_zone_name(vsm_zone_h zone)
658 {
659     LOGS("");
660     return zone == NULL ? NULL : zone->name;
661 }
662 API int vsm_is_host_zone(vsm_zone_h zone)
663 {
664     LOGS("");
665     if (zone == NULL)
666         return -VSM_ERROR_INVALID;
667
668     LOGI("zone->parent == zone is " << (zone->parent == zone ? 1 : 0));
669     return zone->parent == zone ? 1 : 0;
670 }
671 API vsm_zone_h vsm_join_zone(vsm_zone_h  /*zone*/)
672 {
673     LOGS("");
674     return NULL;
675 }
676 API int vsm_canonicalize_path(const char *input_path, char **output_path)
677 {
678     LOGS(""<<input_path);
679     *output_path = strdup(input_path);
680     int len = strlen(input_path);
681     return len;
682 }
683
684 // Note: support the newer API (incomaptible with older)
685 API const char *vsm_error_string(vsm_error_e error)
686 {
687     LOGS("");
688     callcheck();
689     if (error < 0 || error > VSM_MAX_ERROR) {
690         return NULL;
691     }
692     return vsm_error_strtab[error];
693 }
694
695 API struct vsm_zone *vsm_lookup_zone_by_terminal_id(struct vsm_context *ctx, int terminal)
696 {
697     LOGS("terminal=" << terminal);
698     callcheck();
699     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
700     Zone zone;
701     VsmString id;
702     if (!w->client) return NULL;
703     if (w->client->vsm_lookup_zone_by_terminal_id(terminal, &id) != VSMCLIENT_SUCCESS)
704         return NULL;
705     w->client->vsm_lookup_zone_by_id(id, &zone);
706     return wrap_vsm_zone(w, zone);
707 }
708
709 API void vsm_array_string_free(VsmArrayString astring)
710 {
711     if (!astring) {
712         return;
713     }
714     for (char** ptr = astring; *ptr; ++ptr) {
715         vsm_string_free(*ptr);
716     }
717     free(astring);
718 }
719
720 API void vsm_string_free(VsmString string)
721 {
722     free(string);
723 }
724
725 API int vsm_add_event_callback(vsm_context_h, vsm_zone_event_cb, void*) {
726     LOGS("");
727     return 0;
728 }
729 API int vsm_del_event_callback(vsm_context_h, int) {
730     LOGS("");
731     return 0;
732 }
733 API int vsm_add_state_callback(vsm_context_h , vsm_zone_state_cb , void *) {
734     LOGS("");
735     return 0;
736 }
737 API int vsm_del_state_callback(vsm_context_h , int ) {
738     LOGS("");
739     return 0;
740 }
741 API int vsm_down_netdev(vsm_netdev_h) {
742     LOGS("");
743     return 0;
744 }
745 API vsm_zone* vsm_get_foreground(vsm_context_h ctx) {
746     LOGS("");
747     //return ((struct vasum_ops *)(ctx->vsm_ops))->get_foreground(ctx);
748     return dummy_ops.get_foreground(ctx);
749 }
750 API int vsm_get_host_pid(vsm_zone_h, pid_t) {
751     LOGS("");
752     return 0;
753 }
754 API int vsm_get_ip_addr_netdev(vsm_netdev_h, vsm_netdev_addr_t, char*, int) {
755     LOGS("");
756     return 0;
757 }
758 API void* vsm_get_userdata(vsm_zone_h) {
759     LOGS("");
760     return NULL;
761 }
762 API int vsm_get_zone_id(vsm_zone_h zone) {
763     LOGS("");
764     if (zone == NULL)
765         return -VSM_ERROR_INVALID;
766     return zone->id;
767 }
768 API vsm_zone_state_t vsm_get_zone_state(vsm_zone_h zone) {
769     LOGS("");
770     if (zone == NULL)
771         return static_cast<vsm_zone_state_t>(-VSM_ERROR_INVALID);
772     return zone->state;
773 }
774 API int vsm_get_zone_terminal(vsm_zone_h) {
775     LOGS("");
776     return -VSM_ERROR_NOT_SUPPORTED;
777 }
778 API const char *vsm_get_zone_type(vsm_zone_h zone) {
779     LOGS("");
780     return zone == NULL ? NULL : zone->type;
781 }
782 API int vsm_is_equivalent_zone(vsm_context_h, pid_t) {
783     LOGS("");
784     return 0;
785 }
786 API int vsm_is_virtualized() {
787     LOGS("");
788     return 0; /* Running in Host */
789 }
790 // libs/network.c
791 API int vsm_set_ip_addr_netdev(vsm_netdev_h, vsm_netdev_addr_t, const char*, int) {
792     LOGS("");
793     return 0;
794 }
795 API int vsm_up_netdev(vsm_netdev_h) {
796     LOGS("");
797     return 0;
798 }
799 // libs/zone.c
800 API int vsm_set_userdata(vsm_zone_h, void*) {
801     LOGS("");
802     return 0;
803 }
804 API int vsm_state_change_watch_callback(struct vsm_context * /*ctx*/, char * /*name*/,
805                     int  /*state*/, int  /*event*/) {
806     LOGS("");
807     return 0;
808 }
809 // libs/vsm_signal.c
810 API int vsm_signal_state_broadcast(struct mxe_engine * /*engine*/, const char * /*zone_name*/, int  /*state*/) {
811     LOGS("");
812     return 0;
813 }
814 API int vsm_signal_event_broadcast(struct mxe_engine * /*engine*/, const char * /*zone_name*/, int  /*event*/) {
815     LOGS("");
816     return 0;
817 }
818 } // extern "C"