2 * Copyright 2017 IoT.bzh
4 * author: Loïc Collignon <loic.collignon@iot.bzh>
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.
21 #include <sys/types.h>
25 #include <linux/limits.h>
26 #include <json-c/json.h>
29 #define AFB_BINDING_VERSION 2
30 #include <afb/afb-binding.h>
34 #define DBFILE "/ll-database-binding.db"
35 #define USERNAME "agl"
36 #define APPNAME "firefox"
38 // ----- Globals -----
42 // ----- Binding's declarations -----
43 int ll_database_binding_init();
44 void verb_read(struct afb_req req);
45 void verb_update(struct afb_req req);
46 void verb_delete(struct afb_req req);
48 void verb_insert(struct afb_req req);
49 void verb_update(struct afb_req req);
50 void verb_delete(struct afb_req req);
51 void verb_read(struct afb_req req);
53 // ----- Binding's implementations -----
56 * @brief Initialize the binding.
57 * @return Exit code, zero if success.
59 int ll_database_binding_init()
62 struct passwd* result;
67 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
68 if (bufsize == -1) bufsize = 16384;
69 buf = malloc(bufsize);
72 AFB_ERROR("Allocation failed!");
76 ret = getpwuid_r(getuid(), &pwd, buf, bufsize, &result);
80 if (ret == 0) AFB_ERROR("User not found");
81 else AFB_ERROR("getpwuid_r failed with %d code", ret);
85 bufsize = strlen(result->pw_dir) + strlen(DBFILE) + 1;
86 database_file = malloc(bufsize);
87 if (database_file == NULL)
90 AFB_ERROR("Allocation failed!");
94 memset(database_file, 0, bufsize);
95 strcat(database_file, result->pw_dir);
96 strcat(database_file, DBFILE);
99 AFB_INFO("The database file is '%s'", database_file);
101 if ((ret = db_create(&database, NULL, 0)) != 0)
103 AFB_ERROR("Failed to create database: %s.", db_strerror(ret));
108 if ((ret = database->open(database, NULL, database_file, NULL, DB_BTREE, DB_CREATE, 0664)) != 0)
110 AFB_ERROR("Failed to open the '%s' database: %s.", database_file, db_strerror(ret));
111 database->close(database, 0);
120 * @brief Handle the @c read verb.
121 * @param[in] req The query.
123 void verb_insert(struct afb_req req)
133 struct json_object* args;
134 struct json_object* item;
136 args = afb_req_json(req);
140 afb_req_fail(req, "No argument provided.", NULL);
144 if (!json_object_object_get_ex(args, "key", &item) || !item) tag = NULL;
145 else tag = json_object_get_string(item);
147 if (!tag || !strlen(tag))
149 afb_req_fail(req, "No tag provided.", NULL);
153 if (!json_object_object_get_ex(args, "value", &item) || !item) value = NULL;
154 else value = json_object_get_string(item);
156 if (!value || !strlen(value))
158 afb_req_fail(req, "No value provided.", NULL);
162 rkey = malloc(strlen(USERNAME) + strlen(APPNAME) + strlen(tag) + 3);
163 strcpy(rkey, USERNAME);
165 strcat(rkey, APPNAME);
169 AFB_INFO("insert: key=%s, value=%s", rkey, value);
171 memset(&key, 0, sizeof(key));
172 memset(&data, 0, sizeof(data));
175 key.size = strlen(rkey);
177 data.data = (void*)value;
178 data.size = strlen(value);
180 if ((ret = database->put(database, NULL, &key, &data, DB_NOOVERWRITE)) == 0)
181 afb_req_success_f(req, NULL, "db success: insertion %s=%s.", (char*)key.data, (char*)data.data);
183 afb_req_fail_f(req, "Failed to insert datas.", "db fail: insertion : %s=%s - %s", (char*)key.data, (char*)data.data, db_strerror(ret));
187 void verb_update(struct afb_req req)
197 struct json_object* args;
198 struct json_object* item;
200 args = afb_req_json(req);
201 // username should be get from identity binding
202 // application should be get from smack
203 // tag should be get using get_json_string(args, "tag");
207 afb_req_fail(req, "No argument provided.", NULL);
211 if (!json_object_object_get_ex(args, "tag", &item) || !item) tag = NULL;
212 else tag = json_object_get_string(item);
214 if (!tag || !strlen(tag))
216 afb_req_fail(req, "No tag provided.", NULL);
220 if (!json_object_object_get_ex(args, "value", &item) || !item) value = NULL;
221 else value = json_object_get_string(item);
223 if (!value || !strlen(value))
225 afb_req_fail(req, "No value provided.", NULL);
229 rkey = malloc(strlen(USERNAME) + strlen(APPNAME) + strlen(tag) + 3);
230 strcpy(rkey, USERNAME);
232 strcat(rkey, APPNAME);
236 AFB_INFO("update: key=%s, value=%s", rkey, value);
238 memset(&key, 0, sizeof(key));
239 memset(&data, 0, sizeof(data));
242 key.size = strlen(rkey);
244 data.data = (void*)value;
245 data.size = strlen(value);
247 if ((ret = database->put(database, NULL, &key, &data, 0)) == 0)
248 afb_req_success_f(req, NULL, "db success: update %s=%s.", (char*)key.data, (char*)data.data);
250 afb_req_fail_f(req, "Failed to update datas.", "db fail: update %s=%s - %s", (char*)key.data, (char*)data.data, db_strerror(ret));
254 void verb_delete(struct afb_req req)
262 struct json_object* args;
263 struct json_object* item;
265 args = afb_req_json(req);
269 afb_req_fail(req, "No argument provided.", NULL);
273 if (!json_object_object_get_ex(args, "tag", &item) || !item) tag = NULL;
274 else tag = json_object_get_string(item);
276 if (!tag || !strlen(tag))
278 afb_req_fail(req, "No tag provided.", NULL);
282 rkey = malloc(strlen(USERNAME) + strlen(APPNAME) + strlen(tag) + 3);
283 strcpy(rkey, USERNAME);
285 strcat(rkey, APPNAME);
289 AFB_INFO("delete: key=%s", rkey);
291 memset(&key, 0, sizeof(key));
294 key.size = strlen(rkey);
296 if ((ret = database->del(database, NULL, &key, 0)) == 0)
297 afb_req_success_f(req, NULL, "db success: delete %s.", (char *)key.data);
299 afb_req_fail_f(req, "Failed to delete datas.", "db fail: delete %s - %s", (char*)key.data, db_strerror(ret));
303 void verb_read(struct afb_req req)
314 struct json_object* args;
315 struct json_object* item;
316 struct json_object* result;
317 struct json_object* val;
319 args = afb_req_json(req);
323 afb_req_fail(req, "No argument provided.", NULL);
327 if (!json_object_object_get_ex(args, "tag", &item) || !item) tag = NULL;
328 else tag = json_object_get_string(item);
330 if (!tag || !strlen(tag))
332 afb_req_fail(req, "No tag provided.", NULL);
336 rkey = malloc(strlen(USERNAME) + strlen(APPNAME) + strlen(tag) + 3);
337 strcpy(rkey, USERNAME);
339 strcat(rkey, APPNAME);
343 AFB_INFO("update: key=%s, value=%s", rkey, value);
345 memset(&key, 0, sizeof(key));
346 memset(&data, 0, sizeof(data));
347 memset(&value, 0, 4096);
350 key.size = strlen(rkey);
354 data.flags = DB_DBT_USERMEM;
356 if ((ret = database->get(database, NULL, &key, &data, 0)) == 0)
358 result = json_object_new_object();
359 val = json_tokener_parse((char*)data.data);
360 json_object_object_add(result, "value", val ? val : json_object_new_string((char*)data.data));
362 afb_req_success_f(req, result, "db success: read %s=%s.", (char*)key.data, (char*)data.data);
365 afb_req_fail_f(req, "Failed to read datas.", "db fail: read %s - %s", (char*)key.data, db_strerror(ret));
369 // ----- Binding's configuration -----
370 static const struct afb_auth ll_database_binding_auths[] = {
373 static const afb_verb_v2 ll_database_binding_verbs[]= {
374 REGISTER_VERB(insert, NULL, NULL, AFB_SESSION_NONE_V2),
375 REGISTER_VERB(update, NULL, NULL, AFB_SESSION_NONE_V2),
376 REGISTER_VERB(delete, NULL, NULL, AFB_SESSION_NONE_V2),
377 REGISTER_VERB(read, NULL, NULL, AFB_SESSION_NONE_V2),
381 const struct afb_binding_v2 afbBindingV2 = {
382 .api = "ll-database",
383 .specification = NULL,
384 .verbs = ll_database_binding_verbs,
386 .init = ll_database_binding_init,