2 * Copyright (C) 2016, 2017 "IoT.bzh"
3 * Author José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #define NO_BINDING_VERBOSE_MACRO
28 #include "afb-api-so.h"
29 #include "afb-api-so-v1.h"
30 #include "afb-api-so-v2.h"
33 int afb_api_so_timeout = 15;
35 void afb_api_so_set_timeout(int to)
37 afb_api_so_timeout = to;
40 static int load_binding(const char *path, int force)
45 // This is a loadable library let's check if it's a binding
47 handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
50 ERROR("binding [%s] not loadable: %s", path, dlerror());
52 INFO("binding [%s] not loadable: %s", path, dlerror());
56 /* retrieves the register function */
57 rc = afb_api_so_v2_add(path, handle);
59 /* error when loading a valid v2 binding */
62 rc = afb_api_so_v1_add(path, handle);
64 /* error when loading a valid v1 binding */
68 /* not a v1 binding */
70 ERROR("binding [%s] is not an AFB binding", path);
72 INFO("binding [%s] is not an AFB binding", path);
84 int afb_api_so_add_binding(const char *path)
86 return load_binding(path, 1);
89 static int adddirs(char path[PATH_MAX], size_t end)
95 /* open the DIR now */
98 ERROR("can't scan binding directory %s, %m", path);
101 INFO("Scanning dir=[%s] for bindings", path);
103 /* scan each entry */
111 ERROR("read error while scanning directory %.*s: %m", (int)(end - 1), path);
115 len = strlen(dent->d_name);
116 if (len + end >= PATH_MAX) {
117 ERROR("path too long while scanning bindings for %s", dent->d_name);
120 if (dent->d_type == DT_DIR) {
121 /* case of directories */
122 if (dent->d_name[0] == '.') {
125 if (dent->d_name[1] == '.' && len == 2)
128 memcpy(&path[end], dent->d_name, len+1);
129 adddirs(path, end+len);;
130 } else if (dent->d_type == DT_REG) {
132 if (memcmp(&dent->d_name[len - 3], ".so", 4))
134 memcpy(&path[end], dent->d_name, len+1);
135 if (load_binding(path, 0) < 0)
143 int afb_api_so_add_directory(const char *path)
146 char buffer[PATH_MAX];
148 length = strlen(path);
149 if (length >= sizeof(buffer)) {
150 ERROR("path too long %lu [%.99s...]", (unsigned long)length, path);
154 memcpy(buffer, path, length + 1);
155 return adddirs(buffer, length);
158 int afb_api_so_add_path(const char *path)
163 rc = stat(path, &st);
165 ERROR("Invalid binding path [%s]: %m", path);
166 else if (S_ISDIR(st.st_mode))
167 rc = afb_api_so_add_directory(path);
168 else if (strstr(path, ".so"))
169 rc = load_binding(path, 0);
171 INFO("not a binding [%s], skipped", path);
175 int afb_api_so_add_pathset(const char *pathset)
177 static char sep[] = ":";
180 ps = strdupa(pathset);
182 p = strsep(&ps, sep);
185 if (afb_api_so_add_path(p) < 0)