2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Krzysztof Dynowski <k.dynowski@samsung.com>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
22 * @author Krzysztof Dynowski (k.dynowski@samsung.com)
23 * @brief Vasum old API wrapper to slp client lib
26 #define __VASUM_WRAPPER_SOURCE__
32 #include "vasum-client-impl.hpp"
33 #include "logger/logger.hpp"
34 #include "logger/backend-journal.hpp"
36 #include "wrapper-compatibility.h"
43 std::vector<vsm_netdev> netdevs;
50 struct vsm_zone hq_root;
51 std::vector<WrappedZone> zones;
61 #define offsetof(type, memb) ((size_t)&((type *)0)->memb)
67 #define container_of(ptr, type, memb) (\
68 (type *)((char *)(ptr) - offsetof(type, memb)))
71 #define UNUSED(x) ((void)(x))
73 #define vsm_error_t vsm_error_s
74 #define vsm_attach_command_t vsm_attach_command_s
75 #define vsm_attach_options_t vsm_attach_options_s
76 #define vsm_zone_state_cb vsm_zone_state_changed_cb
78 void __attribute__ ((constructor)) wrapper_load(void);
79 void __attribute__ ((destructor)) wrapper_unload(void);
80 static void init_wrapper();
81 extern struct vasum_ops dummy_ops;
83 using namespace logger;
84 void wrapper_load(void)
86 Logger::setLogLevel(LogLevel::TRACE);
87 Logger::setLogBackend(new SystemdJournalBackend());
91 void wrapper_unload(void)
93 if (wrap.glib_stop) Client::vsm_stop_glib_loop();
97 static void callcheck()
104 if (wrap.done) return ;
105 memset(&wrap,0,sizeof(wrap));
110 static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, VsmZone zone, bool create = false)
115 for (auto& zw : w->zones) {
116 if (zw.zone == zone) {
121 w->zones.push_back(WrappedZone());
122 WrappedZone& zw = w->zones.back();
123 zw.client = w->client;
125 zw.vz.name = zone->id;
127 zw.vz.user_data = NULL;
128 zw.vz.rootfs_path = zone->rootfs_path;
129 zw.vz.parent = &zw.vz;
130 LOGI("return (create) zone " << zone->id);
131 return &w->zones.back().vz;
133 LOGE("return zone NULL");
137 static int wrap_error(VsmStatus st, const Client *c)
139 if (st == VSMCLIENT_SUCCESS) LOGI("return success " << st);
140 else LOGE("return error " << st << "m=" << (c ? c->vsm_get_status_message() : "n/a"));
142 case VSMCLIENT_SUCCESS: return VSM_ERROR_NONE;
143 case VSMCLIENT_CUSTOM_ERROR: return -VSM_ERROR_GENERIC;
144 case VSMCLIENT_IO_ERROR: return -VSM_ERROR_IO;
145 case VSMCLIENT_OPERATION_FAILED: return -VSM_ERROR_NOT_PERMITTED;
146 case VSMCLIENT_INVALID_ARGUMENT: return -VSM_ERROR_INVALID;
147 case VSMCLIENT_OTHER_ERROR: return -VSM_ERROR_GENERIC;
149 return -VSM_ERROR_GENERIC;
152 static void init_context_wrap(WrappedContext *w)
154 Client::vsm_start_glib_loop();
156 w->client = new Client();
157 VsmStatus st = w->client->createSystem();
158 wrap_error(st, w->client);
160 memset(&w->hq_ctx, 0, sizeof(w->hq_ctx));
161 memset(&w->hq_root, 0, sizeof(w->hq_root));
163 vsm_context *ctx = &w->hq_ctx;
164 adt_init_list(&ctx->listeners);
166 ctx->root_zone = &w->hq_root;
167 ctx->root_zone->name = (char*)"";
168 ctx->root_zone->id=0;
169 ctx->root_zone->rootfs_path = (char*)"/";
171 ctx->root_zone->terminal = -1;
172 ctx->root_zone->state = VSM_ZONE_STATE_RUNNING;
173 ctx->root_zone->user_data = ctx->root_zone;
175 ctx->root_zone->parent = ctx->root_zone;
176 ctx->root_zone->ctx = ctx;
178 pthread_rwlock_init(&ctx->root_zone->lock, NULL);
179 adt_init_list(&ctx->root_zone->netdevs);
180 adt_init_list(&ctx->root_zone->devices);
181 adt_init_list(&ctx->root_zone->children);
183 pthread_rwlock_init(&ctx->lock, NULL);
184 adt_init_list(&ctx->listeners);
185 adt_init_list(&ctx->sc_listeners);
186 adt_init_list(&ctx->ev_listeners);
188 //struct mainloop *mainloop = mainloop_create();
189 //struct mxe_engine *engine = mxe_prepare_engine(mainloop, ctx);
190 //struct mxe_endpoint *ep = mxe_create_client(engine, SERVICEPATH);
192 ctx->foreground_zone = ctx->root_zone;
193 ctx->vsm_ops = &dummy_ops;
194 ctx->error = VSM_ERROR_NONE;
198 API vsm_context_h vsm_create_context(void)
200 LOGS(""); callcheck();
201 WrappedContext *w = new WrappedContext();
202 init_context_wrap(w);
204 vsm_context *ctx = &w->hq_ctx;
208 API int vsm_cleanup_context(vsm_context_h ctx)
210 LOGS(""); callcheck();
211 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
212 if (w->client != NULL) {
216 for (auto& zw : w->zones) {
221 return VSM_ERROR_NONE;
224 static const char *const vsm_error_strtab[] = {
228 "Operation cancelled",
230 "Connection refused",
233 "Input/Output error",
238 "Operation not permitted",
239 "Function not implemented",
240 "Operation not supported",
246 API vsm_error_e vsm_last_error(struct vsm_context *ctx)
250 return static_cast<vsm_error_e>(-1);
253 API const char *vsm_error_string(vsm_error_e error)
255 LOGS(""); callcheck();
256 if (error < 0 || error > VSM_MAX_ERROR) {
259 return vsm_error_strtab[error];
262 API int vsm_get_poll_fd(struct vsm_context *ctx)
264 LOGS(""); callcheck();
265 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
267 //FIXME Client should create Dispatcher and pass to IPCConnection
268 // now: IPCConnection has field ThreadWrapper
269 //return w->client->getEventPoll().getPollFD();
272 API int vsm_enter_eventloop(struct vsm_context *ctx, int flags, int timeout)
274 LOGS(""); callcheck();
277 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
279 //FIXME Client should create Dispatcher and pass to IPCConnection
280 // now: IPCConnection has field ThreadWrapper
281 //TODO Use EventPoll from Dispatcher
285 API int vsm_create_zone(struct vsm_context *ctx, const char *zone_name, const char *template_name, int flag)
287 LOGS("create_zone " << zone_name); callcheck();
288 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
290 //template_name = NULL; //template name not supported by libvasum-client
291 if (!w->client) return VSM_ERROR_GENERIC;
292 VsmStatus st = w->client->vsm_create_zone(zone_name, template_name);
293 if (st != VSMCLIENT_SUCCESS) {
294 LOGE("vsm_create_zone(" << zone_name << ") = " << st);
296 return wrap_error(st, w->client);
299 API int vsm_destroy_zone(struct vsm_context *ctx, const char *zone_name, int force)
301 LOGS("zone=" << zone_name); callcheck();
302 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
304 if (!w->client) return VSM_ERROR_GENERIC;
305 VsmStatus st = w->client->vsm_destroy_zone(zone_name);
306 if (st == VSMCLIENT_SUCCESS) {
307 auto zonebyname = [zone_name](const WrappedZone& v) {return v.zone->id == zone_name;};
308 auto zonelist = std::remove_if(w->zones.begin(), w->zones.end(), zonebyname);
309 w->zones.erase(zonelist);
311 return wrap_error(st, w->client);
314 API int vsm_start_zone(struct vsm_context *ctx, const char *zone_name)
316 LOGS("zone=" << zone_name); 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);
323 API int vsm_shutdown_zone(struct vsm_context *ctx, const char *zone_name, int force)
325 LOGS("zone=" << zone_name); callcheck();
326 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
328 if (!w->client) return VSM_ERROR_GENERIC;
329 VsmStatus st = w->client->vsm_shutdown_zone(zone_name);
330 return wrap_error(st, w->client);
333 API int vsm_lock_zone(struct vsm_context *ctx, const char *zone_name, int shutdown)
335 LOGS("zone=" << zone_name); callcheck();
336 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
338 if (!w->client) return VSM_ERROR_GENERIC;
339 VsmStatus st = w->client->vsm_lock_zone(zone_name);
340 return wrap_error(st, w->client);
343 API int vsm_unlock_zone(struct vsm_context *ctx, const char *zone_name)
345 LOGS("zone=" << zone_name); callcheck();
346 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
347 if (!w->client) return VSM_ERROR_GENERIC;
348 VsmStatus st = w->client->vsm_lock_zone(zone_name);
349 return wrap_error(st, w->client);
352 API int vsm_set_foreground(struct vsm_zone *zone)
354 LOGS(""); callcheck();
355 WrappedZone *w = container_of(zone, WrappedZone, vz);
356 if (!w->client) return VSM_ERROR_GENERIC;
357 VsmStatus st = w->client->vsm_set_active_zone(zone->name);
358 return wrap_error(st, w->client);
361 //execute command in specified zone
362 API int vsm_attach_zone(struct vsm_context *ctx,
363 const char *zone_name,
364 vsm_attach_command_t *command,
365 vsm_attach_options_t *opts,
366 pid_t *attached_process)
368 return dummy_ops.attach_zone(ctx, zone_name, command, opts,
372 //execute command in specified zone and wait
373 API int vsm_attach_zone_wait(struct vsm_context *ctx,
374 const char *zone_name,
375 vsm_attach_command_t *command,
376 vsm_attach_options_t *opts)
378 return dummy_ops.attach_zone_wait(ctx, zone_name, command, opts);
381 API int vsm_iterate_zone(struct vsm_context *ctx, void (*callback)(struct vsm_zone *zone, void *user_data), void *user_data)
383 LOGS(""); callcheck();
384 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
385 if (!w->client) return -VSM_ERROR_GENERIC;
386 callback(ctx->root_zone, user_data);
387 for (auto& z : w->zones) {
388 callback(&z.vz, user_data);
393 API struct vsm_zone *vsm_lookup_zone_by_name(struct vsm_context *ctx, const char *path)
395 LOGS("name=" << path); callcheck();
396 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
398 if (!w->client) return NULL;
399 //CHECK if path is same as zone_name
400 if (w->client->vsm_lookup_zone_by_id(path, &zone) != VSMCLIENT_SUCCESS)
402 return wrap_vsm_zone(w, zone, true);
405 API struct vsm_zone *vsm_lookup_zone_by_pid(struct vsm_context *ctx, pid_t pid)
407 LOGS("pid=" << pid); callcheck();
408 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
411 if (!w->client) return NULL;
412 if (w->client->vsm_lookup_zone_by_pid(pid, &id) != VSMCLIENT_SUCCESS) {
413 LOGE("vsm_lookup_zone_by_pid(" << pid << ") error");
416 if (::strcmp(id, "host") == 0) {
417 return w->hq_ctx.root_zone;
419 w->client->vsm_lookup_zone_by_id(id, &zone); //zone is malloced
420 return wrap_vsm_zone(w, zone);
423 API struct vsm_zone *vsm_lookup_zone_by_terminal_id(struct vsm_context *ctx, int terminal)
425 LOGS("terminal=" << terminal); callcheck();
426 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
429 if (!w->client) return NULL;
430 if (w->client->vsm_lookup_zone_by_terminal_id(terminal, &id) != VSMCLIENT_SUCCESS)
432 w->client->vsm_lookup_zone_by_id(id, &zone);
433 return wrap_vsm_zone(w, zone);
436 API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_cb callback, void *user_data)
438 LOGS(""); callcheck();
439 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
440 VsmSubscriptionId subscriptionId;
442 auto dbus_cb = [=](const char* id, const char* dbusAddress, void* data) ->
445 //TODO what are valid state, event
447 w->client->vsm_lookup_zone_by_id(id, &zone);
448 callback(wrap_vsm_zone(w, zone), data);
450 w->client->vsm_add_state_callback(dbus_cb, user_data, &subscriptionId);
451 return (int)subscriptionId;
454 API int vsm_del_state_changed_callback(struct vsm_context *ctx, int handle)
456 LOGS(""); callcheck();
457 WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
458 VsmSubscriptionId subscriptionId = (VsmSubscriptionId)handle;
459 VsmStatus st = w->client->vsm_del_state_callback(subscriptionId);
460 return wrap_error(st, w->client);
463 API int vsm_grant_device(struct vsm_zone *dom, const char *name, uint32_t flags)
465 LOGS(""); callcheck();
466 WrappedZone *w = container_of(dom, WrappedZone, vz);
467 const char *id = dom->name;
469 w->client->vsm_lookup_zone_by_id(id, &zone);
470 VsmStatus st = w->client->vsm_grant_device(id, name, flags);
471 return wrap_error(st, w->client);
474 API int vsm_revoke_device(struct vsm_zone *dom, const char *name)
476 LOGS(""); callcheck();
477 WrappedZone *w = container_of(dom, WrappedZone, vz);
478 const char *id = dom->name;
479 VsmStatus st = w->client->vsm_revoke_device(id, name);
480 return wrap_error(st, w->client);
483 API struct vsm_netdev *vsm_create_netdev(struct vsm_zone *zone, vsm_netdev_type_t type, const char *target, const char *netdev)
485 LOGS(""); callcheck();
491 WrappedZone *w = container_of(zone, WrappedZone, vz);
492 const char *id = zone->name;
494 if (type == VSM_NETDEV_VETH)
495 st = w->client->vsm_create_netdev_veth(id, target, netdev);
496 else if (type == VSM_NETDEV_PHYS)
497 st = w->client->vsm_create_netdev_phys(id, netdev);
498 else if (type == VSM_NETDEV_MACVLAN) // macvlan_mode from if_link.h
499 st = w->client->vsm_create_netdev_macvlan(id, target, netdev, MACVLAN_MODE_BRIDGE);
501 LOGE("Invalid arguments");
502 //ctx->error = VSM_ERROR_INVALID;
506 if (st != VSMCLIENT_SUCCESS) {
507 LOGE("vsm_create_netdev(" << netdev << ") = " << st);
513 vnd.name = (char*)netdev; //FIXME? copy content of string
515 w->netdevs.push_back(vnd); //copy pushed to vector
516 return &w->netdevs.back(); //pointer to struct on vector
519 API int vsm_destroy_netdev(struct vsm_zone *zone, struct vsm_netdev *netdev)
521 LOGS(""); callcheck();
522 WrappedZone *w = container_of(zone, WrappedZone, vz);
524 VsmStatus st = w->client->vsm_destroy_netdev(zone->name, netdev->name);
525 if (st == VSMCLIENT_SUCCESS) {
526 auto devbyname = [netdev](const vsm_netdev& v) {return ::strcmp(v.name, netdev->name) == 0;};
527 auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname);
528 if (devlist != w->netdevs.end()) {
529 w->netdevs.erase(devlist);
532 return wrap_error(st, w->client);
535 API int vsm_iterate_netdev(struct vsm_zone *zone, void (*callback)(struct vsm_netdev *, void *user_data), void *user_data)
537 LOGS(""); callcheck();
538 WrappedZone *w = container_of(zone, WrappedZone, vz);
539 for (auto nd : w->netdevs) {
540 callback(&nd, user_data);
545 API struct vsm_netdev *vsm_lookup_netdev_by_name(struct vsm_zone *zone, const char *name)
547 LOGS(""); callcheck();
548 WrappedZone *w = container_of(zone, WrappedZone, vz);
550 VsmStatus st = w->client->vsm_lookup_netdev_by_name(zone->name, name, &nd);
551 if (st == VSMCLIENT_SUCCESS) {
552 auto devbyname = [name](const vsm_netdev& v) {return ::strcmp(v.name, name) == 0;};
553 auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname);
554 if (devlist != w->netdevs.end()) {
561 API int vsm_declare_file(struct vsm_context *ctx, vsm_fso_type_t ftype, const char *path, int flags, vsm_mode_t mode)
563 LOGS(""); callcheck();
569 //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
570 return VSM_ERROR_NONE;
573 API int vsm_declare_mount(struct vsm_context *ctx,
580 LOGS(""); callcheck();
587 //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
588 return VSM_ERROR_NONE;
591 API int vsm_declare_link(struct vsm_context *ctx, const char *source, const char *target)
593 LOGS("src=" << source << "dst=" << target); callcheck();
597 //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
598 return VSM_ERROR_NONE;
601 API int vsm_add_state_changed_callback(vsm_context_h /*ctx*/, vsm_zone_state_changed_cb /*callback*/, void * /*user_data*/)
603 return VSM_ERROR_NONE;
605 API int vsm_del_state_changed_callback(vsm_context_h /*ctx*/, int /*id*/)
607 return VSM_ERROR_NONE;
609 API const char * vsm_get_zone_rootpath(vsm_zone_h /*zone*/)
613 API const char * vsm_get_zone_name(vsm_zone_h /*zone*/)
617 API int vsm_is_host_zone(vsm_zone_h /*zone*/)
619 return VSM_ERROR_NONE;
621 API vsm_zone_h vsm_join_zone(vsm_zone_h /*zone*/)
625 API int vsm_canonicalize_path(const char * /*input_path*/, char ** /*output_path*/)
627 return VSM_ERROR_NONE;