1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci
16d9f0492fSopenharmony_ci#include <dirent.h>
17d9f0492fSopenharmony_ci#include <dlfcn.h>
18d9f0492fSopenharmony_ci#include <stdio.h>
19d9f0492fSopenharmony_ci#include <stdlib.h>
20d9f0492fSopenharmony_ci#include <string.h>
21d9f0492fSopenharmony_ci#include <linux/limits.h>
22d9f0492fSopenharmony_ci
23d9f0492fSopenharmony_ci#include "beget_ext.h"
24d9f0492fSopenharmony_ci#include "config_policy_utils.h"
25d9f0492fSopenharmony_ci#include "init_utils.h"
26d9f0492fSopenharmony_ci#include "list.h"
27d9f0492fSopenharmony_ci#include "securec.h"
28d9f0492fSopenharmony_ci#include "modulemgr.h"
29d9f0492fSopenharmony_ci
30d9f0492fSopenharmony_ci#define MODULE_SUFFIX_D ".z.so"
31d9f0492fSopenharmony_ci#ifdef SUPPORT_64BIT
32d9f0492fSopenharmony_ci#define MODULE_LIB_NAME "lib64"
33d9f0492fSopenharmony_ci#else
34d9f0492fSopenharmony_ci#define MODULE_LIB_NAME "lib"
35d9f0492fSopenharmony_ci#endif
36d9f0492fSopenharmony_ci#define LIB_NAME_LEN 3
37d9f0492fSopenharmony_ci
38d9f0492fSopenharmony_cistruct tagMODULE_MGR {
39d9f0492fSopenharmony_ci    ListNode modules;
40d9f0492fSopenharmony_ci    const char *name;
41d9f0492fSopenharmony_ci    MODULE_INSTALL_ARGS installArgs;
42d9f0492fSopenharmony_ci};
43d9f0492fSopenharmony_ci
44d9f0492fSopenharmony_ciMODULE_MGR *ModuleMgrCreate(const char *name)
45d9f0492fSopenharmony_ci{
46d9f0492fSopenharmony_ci    MODULE_MGR *moduleMgr;
47d9f0492fSopenharmony_ci
48d9f0492fSopenharmony_ci    BEGET_CHECK(name != NULL, return NULL);
49d9f0492fSopenharmony_ci
50d9f0492fSopenharmony_ci    moduleMgr = (MODULE_MGR *)malloc(sizeof(MODULE_MGR));
51d9f0492fSopenharmony_ci    BEGET_CHECK(moduleMgr != NULL, return NULL);
52d9f0492fSopenharmony_ci    OH_ListInit(&(moduleMgr->modules));
53d9f0492fSopenharmony_ci    moduleMgr->name = strdup(name);
54d9f0492fSopenharmony_ci    if (moduleMgr->name == NULL) {
55d9f0492fSopenharmony_ci        free((void *)moduleMgr);
56d9f0492fSopenharmony_ci        return NULL;
57d9f0492fSopenharmony_ci    }
58d9f0492fSopenharmony_ci    moduleMgr->installArgs.argc = 0;
59d9f0492fSopenharmony_ci    moduleMgr->installArgs.argv = NULL;
60d9f0492fSopenharmony_ci
61d9f0492fSopenharmony_ci    return moduleMgr;
62d9f0492fSopenharmony_ci}
63d9f0492fSopenharmony_ci
64d9f0492fSopenharmony_civoid ModuleMgrDestroy(MODULE_MGR *moduleMgr)
65d9f0492fSopenharmony_ci{
66d9f0492fSopenharmony_ci    BEGET_CHECK(moduleMgr != NULL, return);
67d9f0492fSopenharmony_ci
68d9f0492fSopenharmony_ci    ModuleMgrUninstall(moduleMgr, NULL);
69d9f0492fSopenharmony_ci    BEGET_CHECK(moduleMgr->name == NULL, free((void *)moduleMgr->name));
70d9f0492fSopenharmony_ci    free((void *)moduleMgr);
71d9f0492fSopenharmony_ci}
72d9f0492fSopenharmony_ci
73d9f0492fSopenharmony_ci/*
74d9f0492fSopenharmony_ci * Module Item related api
75d9f0492fSopenharmony_ci */
76d9f0492fSopenharmony_ci
77d9f0492fSopenharmony_ci
78d9f0492fSopenharmony_citypedef struct tagMODULE_ITEM {
79d9f0492fSopenharmony_ci    ListNode node;
80d9f0492fSopenharmony_ci    MODULE_MGR *moduleMgr;
81d9f0492fSopenharmony_ci    const char *name;
82d9f0492fSopenharmony_ci    void *handle;
83d9f0492fSopenharmony_ci} MODULE_ITEM;
84d9f0492fSopenharmony_ci
85d9f0492fSopenharmony_cistatic void ModuleDestroy(ListNode *node)
86d9f0492fSopenharmony_ci{
87d9f0492fSopenharmony_ci    MODULE_ITEM *module;
88d9f0492fSopenharmony_ci
89d9f0492fSopenharmony_ci    BEGET_CHECK(node != NULL, return);
90d9f0492fSopenharmony_ci
91d9f0492fSopenharmony_ci    module = (MODULE_ITEM *)node;
92d9f0492fSopenharmony_ci    BEGET_CHECK(module->name == NULL, free((void *)module->name));
93d9f0492fSopenharmony_ci    BEGET_CHECK(module->handle == NULL, dlclose(module->handle));
94d9f0492fSopenharmony_ci    free((void *)module);
95d9f0492fSopenharmony_ci}
96d9f0492fSopenharmony_ci
97d9f0492fSopenharmony_cistatic MODULE_INSTALL_ARGS *currentInstallArgs = NULL;
98d9f0492fSopenharmony_ci
99d9f0492fSopenharmony_cistatic void *ModuleInstall(MODULE_ITEM *module, int argc, const char *argv[])
100d9f0492fSopenharmony_ci{
101d9f0492fSopenharmony_ci    void *handle;
102d9f0492fSopenharmony_ci    char path[PATH_MAX];
103d9f0492fSopenharmony_ci    int rc;
104d9f0492fSopenharmony_ci
105d9f0492fSopenharmony_ci    module->moduleMgr->installArgs.argc = argc;
106d9f0492fSopenharmony_ci    module->moduleMgr->installArgs.argv = argv;
107d9f0492fSopenharmony_ci
108d9f0492fSopenharmony_ci    BEGET_LOGV("Module install name %s", module->name);
109d9f0492fSopenharmony_ci    if (module->name[0] == '/') {
110d9f0492fSopenharmony_ci        rc = snprintf_s(path, sizeof(path), sizeof(path) - 1, STARTUP_INIT_UT_PATH"%s" MODULE_SUFFIX_D, module->name);
111d9f0492fSopenharmony_ci        BEGET_CHECK(rc >= 0, return NULL);
112d9f0492fSopenharmony_ci    } else {
113d9f0492fSopenharmony_ci        const char *fmt = (InUpdaterMode() == 0) ? "/system/" MODULE_LIB_NAME : "/" MODULE_LIB_NAME;
114d9f0492fSopenharmony_ci        rc = snprintf_s(path, sizeof(path), sizeof(path) - 1,
115d9f0492fSopenharmony_ci            STARTUP_INIT_UT_PATH"%s/%s/lib%s" MODULE_SUFFIX_D, fmt, module->moduleMgr->name, module->name);
116d9f0492fSopenharmony_ci        BEGET_CHECK(rc >= 0, return NULL);
117d9f0492fSopenharmony_ci    }
118d9f0492fSopenharmony_ci    BEGET_LOGV("Module install path %s", path);
119d9f0492fSopenharmony_ci    char *realPath = GetRealPath(path);
120d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(realPath != NULL, return NULL, "Failed to get real path");
121d9f0492fSopenharmony_ci    currentInstallArgs = &(module->moduleMgr->installArgs);
122d9f0492fSopenharmony_ci    handle = dlopen(realPath, RTLD_LAZY | RTLD_GLOBAL);
123d9f0492fSopenharmony_ci    currentInstallArgs = NULL;
124d9f0492fSopenharmony_ci    BEGET_CHECK_ONLY_ELOG(handle != NULL, "ModuleInstall path %s fail %d", realPath, errno);
125d9f0492fSopenharmony_ci    free(realPath);
126d9f0492fSopenharmony_ci    return handle;
127d9f0492fSopenharmony_ci}
128d9f0492fSopenharmony_ci
129d9f0492fSopenharmony_cistatic int ModuleCompare(ListNode *node, void *data)
130d9f0492fSopenharmony_ci{
131d9f0492fSopenharmony_ci    MODULE_ITEM *module = (MODULE_ITEM *)node;
132d9f0492fSopenharmony_ci    const char *name = module->name;
133d9f0492fSopenharmony_ci    if (module->name[0] == '/') {
134d9f0492fSopenharmony_ci        name = strrchr((name), '/') + 1;
135d9f0492fSopenharmony_ci    }
136d9f0492fSopenharmony_ci    if (strncmp(name, "lib", LIB_NAME_LEN) == 0) {
137d9f0492fSopenharmony_ci        name = name + LIB_NAME_LEN;
138d9f0492fSopenharmony_ci    }
139d9f0492fSopenharmony_ci    return strcmp(name, (char *)data);
140d9f0492fSopenharmony_ci}
141d9f0492fSopenharmony_ci
142d9f0492fSopenharmony_ci/*
143d9f0492fSopenharmony_ci * 用于扫描安装指定目录下所有的插件。
144d9f0492fSopenharmony_ci */
145d9f0492fSopenharmony_ciint ModuleMgrInstall(MODULE_MGR *moduleMgr, const char *moduleName,
146d9f0492fSopenharmony_ci                     int argc, const char *argv[])
147d9f0492fSopenharmony_ci{
148d9f0492fSopenharmony_ci    MODULE_ITEM *module;
149d9f0492fSopenharmony_ci    BEGET_LOGV("ModuleMgrInstall moduleName %s", moduleName);
150d9f0492fSopenharmony_ci    // Get module manager
151d9f0492fSopenharmony_ci    BEGET_CHECK(!(moduleMgr == NULL || moduleName == NULL), return -1);
152d9f0492fSopenharmony_ci
153d9f0492fSopenharmony_ci    module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)moduleName, ModuleCompare);
154d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(module == NULL, return 0, "%s module already exists", moduleName);
155d9f0492fSopenharmony_ci
156d9f0492fSopenharmony_ci    // Create module item
157d9f0492fSopenharmony_ci    module = (MODULE_ITEM *)malloc(sizeof(MODULE_ITEM));
158d9f0492fSopenharmony_ci    BEGET_CHECK(module != NULL, return -1);
159d9f0492fSopenharmony_ci
160d9f0492fSopenharmony_ci    module->handle = NULL;
161d9f0492fSopenharmony_ci    module->moduleMgr = moduleMgr;
162d9f0492fSopenharmony_ci
163d9f0492fSopenharmony_ci    module->name = strdup(moduleName);
164d9f0492fSopenharmony_ci    BEGET_CHECK(module->name != NULL, free(module);
165d9f0492fSopenharmony_ci        return -1);
166d9f0492fSopenharmony_ci
167d9f0492fSopenharmony_ci    // Install
168d9f0492fSopenharmony_ci    module->handle = ModuleInstall(module, argc, argv);
169d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST
170d9f0492fSopenharmony_ci    if (module->handle == NULL) {
171d9f0492fSopenharmony_ci        BEGET_LOGE("Failed to install module %s", module->name);
172d9f0492fSopenharmony_ci        ModuleDestroy((ListNode *)module);
173d9f0492fSopenharmony_ci        return -1;
174d9f0492fSopenharmony_ci    }
175d9f0492fSopenharmony_ci#endif
176d9f0492fSopenharmony_ci    // Add to list
177d9f0492fSopenharmony_ci    OH_ListAddTail(&(moduleMgr->modules), (ListNode *)module);
178d9f0492fSopenharmony_ci
179d9f0492fSopenharmony_ci    return 0;
180d9f0492fSopenharmony_ci}
181d9f0492fSopenharmony_ci
182d9f0492fSopenharmony_ciconst MODULE_INSTALL_ARGS *ModuleMgrGetArgs(void)
183d9f0492fSopenharmony_ci{
184d9f0492fSopenharmony_ci    return currentInstallArgs;
185d9f0492fSopenharmony_ci}
186d9f0492fSopenharmony_ci
187d9f0492fSopenharmony_cistatic int StringEndsWith(const char *srcStr, const char *endStr)
188d9f0492fSopenharmony_ci{
189d9f0492fSopenharmony_ci    int srcStrLen = strlen(srcStr);
190d9f0492fSopenharmony_ci    int endStrLen = strlen(endStr);
191d9f0492fSopenharmony_ci
192d9f0492fSopenharmony_ci    BEGET_CHECK(!(srcStrLen < endStrLen), return -1);
193d9f0492fSopenharmony_ci
194d9f0492fSopenharmony_ci    srcStr += (srcStrLen - endStrLen);
195d9f0492fSopenharmony_ci    BEGET_CHECK(strcmp(srcStr, endStr) != 0, return (srcStrLen - endStrLen));
196d9f0492fSopenharmony_ci    return -1;
197d9f0492fSopenharmony_ci}
198d9f0492fSopenharmony_ci
199d9f0492fSopenharmony_cistatic void ScanModules(MODULE_MGR *moduleMgr, const char *path)
200d9f0492fSopenharmony_ci{
201d9f0492fSopenharmony_ci    BEGET_LOGV("Scan module with name '%s'", path);
202d9f0492fSopenharmony_ci    DIR *dir = opendir(path);
203d9f0492fSopenharmony_ci    BEGET_CHECK(dir != NULL, return);
204d9f0492fSopenharmony_ci    char *moduleName = calloc(PATH_MAX, sizeof(char));
205d9f0492fSopenharmony_ci    while (moduleName != NULL) {
206d9f0492fSopenharmony_ci        struct dirent *file = readdir(dir);
207d9f0492fSopenharmony_ci        if (file == NULL) {
208d9f0492fSopenharmony_ci            break;
209d9f0492fSopenharmony_ci        }
210d9f0492fSopenharmony_ci        if ((file->d_type != DT_REG) && (file->d_type != DT_LNK)) {
211d9f0492fSopenharmony_ci            continue;
212d9f0492fSopenharmony_ci        }
213d9f0492fSopenharmony_ci
214d9f0492fSopenharmony_ci        // Must be ended with MODULE_SUFFIX_D
215d9f0492fSopenharmony_ci        int end = StringEndsWith(file->d_name, MODULE_SUFFIX_D);
216d9f0492fSopenharmony_ci        if (end <= 0) {
217d9f0492fSopenharmony_ci            continue;
218d9f0492fSopenharmony_ci        }
219d9f0492fSopenharmony_ci
220d9f0492fSopenharmony_ci        file->d_name[end] = '\0';
221d9f0492fSopenharmony_ci        int len = sprintf_s(moduleName, PATH_MAX - 1, "%s/%s", path, file->d_name);
222d9f0492fSopenharmony_ci        if (len > 0) {
223d9f0492fSopenharmony_ci            moduleName[len] = '\0';
224d9f0492fSopenharmony_ci            BEGET_LOGI("Scan module with name '%s'", moduleName);
225d9f0492fSopenharmony_ci            ModuleMgrInstall(moduleMgr, moduleName, 0, NULL);
226d9f0492fSopenharmony_ci        }
227d9f0492fSopenharmony_ci    }
228d9f0492fSopenharmony_ci    if (moduleName != NULL) {
229d9f0492fSopenharmony_ci        free(moduleName);
230d9f0492fSopenharmony_ci    }
231d9f0492fSopenharmony_ci    closedir(dir);
232d9f0492fSopenharmony_ci}
233d9f0492fSopenharmony_ci
234d9f0492fSopenharmony_ci/*
235d9f0492fSopenharmony_ci * 用于扫描安装指定目录下所有的插件。
236d9f0492fSopenharmony_ci */
237d9f0492fSopenharmony_ciMODULE_MGR *ModuleMgrScan(const char *modulePath)
238d9f0492fSopenharmony_ci{
239d9f0492fSopenharmony_ci    MODULE_MGR *moduleMgr;
240d9f0492fSopenharmony_ci    char path[PATH_MAX];
241d9f0492fSopenharmony_ci    BEGET_LOGV("ModuleMgrScan moduleName %s", modulePath);
242d9f0492fSopenharmony_ci    moduleMgr = ModuleMgrCreate(modulePath);
243d9f0492fSopenharmony_ci    BEGET_CHECK(moduleMgr != NULL, return NULL);
244d9f0492fSopenharmony_ci
245d9f0492fSopenharmony_ci    if (modulePath[0] == '/') {
246d9f0492fSopenharmony_ci        ScanModules(moduleMgr, modulePath);
247d9f0492fSopenharmony_ci    } else if (InUpdaterMode() == 1) {
248d9f0492fSopenharmony_ci        BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1,
249d9f0492fSopenharmony_ci            "/%s/%s", MODULE_LIB_NAME, modulePath) > 0, free((void *)moduleMgr); return NULL);
250d9f0492fSopenharmony_ci        ScanModules(moduleMgr, path);
251d9f0492fSopenharmony_ci    } else {
252d9f0492fSopenharmony_ci        BEGET_CHECK(snprintf_s(path, sizeof(path), sizeof(path) - 1,
253d9f0492fSopenharmony_ci            "%s/%s", MODULE_LIB_NAME, modulePath) > 0, free((void *)moduleMgr); return NULL);
254d9f0492fSopenharmony_ci        CfgFiles *files = GetCfgFiles(path);
255d9f0492fSopenharmony_ci        for (int i = MAX_CFG_POLICY_DIRS_CNT - 1; files && i >= 0; i--) {
256d9f0492fSopenharmony_ci            if (files->paths[i]) {
257d9f0492fSopenharmony_ci                ScanModules(moduleMgr, files->paths[i]);
258d9f0492fSopenharmony_ci            }
259d9f0492fSopenharmony_ci        }
260d9f0492fSopenharmony_ci        FreeCfgFiles(files);
261d9f0492fSopenharmony_ci    }
262d9f0492fSopenharmony_ci    return moduleMgr;
263d9f0492fSopenharmony_ci}
264d9f0492fSopenharmony_ci
265d9f0492fSopenharmony_ci/*
266d9f0492fSopenharmony_ci * 卸载指定插件。
267d9f0492fSopenharmony_ci */
268d9f0492fSopenharmony_civoid ModuleMgrUninstall(MODULE_MGR *moduleMgr, const char *name)
269d9f0492fSopenharmony_ci{
270d9f0492fSopenharmony_ci    MODULE_ITEM *module;
271d9f0492fSopenharmony_ci    BEGET_CHECK(moduleMgr != NULL, return);
272d9f0492fSopenharmony_ci    // Uninstall all modules if no name specified
273d9f0492fSopenharmony_ci    if (name == NULL) {
274d9f0492fSopenharmony_ci        OH_ListRemoveAll(&(moduleMgr->modules), ModuleDestroy);
275d9f0492fSopenharmony_ci        return;
276d9f0492fSopenharmony_ci    }
277d9f0492fSopenharmony_ci    BEGET_LOGV("ModuleMgrUninstall moduleName %s", name);
278d9f0492fSopenharmony_ci    // Find module by name
279d9f0492fSopenharmony_ci    module = (MODULE_ITEM *)OH_ListFind(&(moduleMgr->modules), (void *)name, ModuleCompare);
280d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(module != NULL, return, "Can not find module %s", name);
281d9f0492fSopenharmony_ci
282d9f0492fSopenharmony_ci    // Remove from the list
283d9f0492fSopenharmony_ci    OH_ListRemove((ListNode *)module);
284d9f0492fSopenharmony_ci    // Destroy the module
285d9f0492fSopenharmony_ci    ModuleDestroy((ListNode *)module);
286d9f0492fSopenharmony_ci}
287d9f0492fSopenharmony_ci
288d9f0492fSopenharmony_ciint ModuleMgrGetCnt(const MODULE_MGR *moduleMgr)
289d9f0492fSopenharmony_ci{
290d9f0492fSopenharmony_ci    BEGET_CHECK(moduleMgr != NULL, return 0);
291d9f0492fSopenharmony_ci    return OH_ListGetCnt(&(moduleMgr->modules));
292d9f0492fSopenharmony_ci}
293d9f0492fSopenharmony_ci
294d9f0492fSopenharmony_citypedef struct tagMODULE_TRAVERSAL_ARGS {
295d9f0492fSopenharmony_ci    void  *cookie;
296d9f0492fSopenharmony_ci    OhosModuleTraversal traversal;
297d9f0492fSopenharmony_ci} MODULE_TRAVERSAL_ARGS;
298d9f0492fSopenharmony_ci
299d9f0492fSopenharmony_cistatic int ModuleTraversalProc(ListNode *node, void *cookie)
300d9f0492fSopenharmony_ci{
301d9f0492fSopenharmony_ci    MODULE_ITEM *module;
302d9f0492fSopenharmony_ci    MODULE_TRAVERSAL_ARGS *args;
303d9f0492fSopenharmony_ci    MODULE_INFO info;
304d9f0492fSopenharmony_ci
305d9f0492fSopenharmony_ci    module = (MODULE_ITEM *)node;
306d9f0492fSopenharmony_ci    args = (MODULE_TRAVERSAL_ARGS *)cookie;
307d9f0492fSopenharmony_ci
308d9f0492fSopenharmony_ci    info.cookie = args->cookie;
309d9f0492fSopenharmony_ci    info.handle = module->handle;
310d9f0492fSopenharmony_ci    info.name = module->name;
311d9f0492fSopenharmony_ci    args->traversal(&info);
312d9f0492fSopenharmony_ci
313d9f0492fSopenharmony_ci    return 0;
314d9f0492fSopenharmony_ci}
315d9f0492fSopenharmony_ci
316d9f0492fSopenharmony_ci/**
317d9f0492fSopenharmony_ci * @brief Traversing all hooks in the HookManager
318d9f0492fSopenharmony_ci *
319d9f0492fSopenharmony_ci * @param moduleMgr HookManager handle.
320d9f0492fSopenharmony_ci *                If hookMgr is NULL, it will use default HookManager
321d9f0492fSopenharmony_ci * @param cookie traversal cookie.
322d9f0492fSopenharmony_ci * @param traversal traversal function.
323d9f0492fSopenharmony_ci * @return None.
324d9f0492fSopenharmony_ci */
325d9f0492fSopenharmony_civoid ModuleMgrTraversal(const MODULE_MGR *moduleMgr, void *cookie, OhosModuleTraversal traversal)
326d9f0492fSopenharmony_ci{
327d9f0492fSopenharmony_ci    MODULE_TRAVERSAL_ARGS args;
328d9f0492fSopenharmony_ci    if (moduleMgr == NULL) {
329d9f0492fSopenharmony_ci        return;
330d9f0492fSopenharmony_ci    }
331d9f0492fSopenharmony_ci
332d9f0492fSopenharmony_ci    args.cookie = cookie;
333d9f0492fSopenharmony_ci    args.traversal = traversal;
334d9f0492fSopenharmony_ci    OH_ListTraversal((ListNode *)(&(moduleMgr->modules)), (void *)(&args), ModuleTraversalProc, 0);
335d9f0492fSopenharmony_ci}
336