1570af302Sopenharmony_ci/*
2570af302Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3570af302Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4570af302Sopenharmony_ci * you may not use this file except in compliance with the License.
5570af302Sopenharmony_ci * You may obtain a copy of the License at
6570af302Sopenharmony_ci *
7570af302Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8570af302Sopenharmony_ci *
9570af302Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10570af302Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11570af302Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12570af302Sopenharmony_ci * See the License for the specific language governing permissions and
13570af302Sopenharmony_ci * limitations under the License.
14570af302Sopenharmony_ci */
15570af302Sopenharmony_ci
16570af302Sopenharmony_ci#include "ns_config.h"
17570af302Sopenharmony_ci
18570af302Sopenharmony_ci#include <ctype.h>
19570af302Sopenharmony_ci#include <stdarg.h>
20570af302Sopenharmony_ci
21570af302Sopenharmony_ci#include "ld_log.h"
22570af302Sopenharmony_ci/*---------------------------- Defines -------------------------------------*/
23570af302Sopenharmony_ci#define MAX_LINE_SIZE         (1024)
24570af302Sopenharmony_ci#define INI_INVALID_KEY     ((char*)-1)
25570af302Sopenharmony_ci
26570af302Sopenharmony_ci#ifdef UNIT_TEST_STATIC
27570af302Sopenharmony_ci    #define UT_STATIC
28570af302Sopenharmony_ci#else
29570af302Sopenharmony_ci    #define UT_STATIC static
30570af302Sopenharmony_ci#endif
31570af302Sopenharmony_citypedef enum _line_status_ {
32570af302Sopenharmony_ci    LINE_UNPROCESSED,
33570af302Sopenharmony_ci    LINE_ERROR,
34570af302Sopenharmony_ci    LINE_EMPTY,
35570af302Sopenharmony_ci    LINE_COMMENT,
36570af302Sopenharmony_ci    LINE_SECTION,
37570af302Sopenharmony_ci    LINE_VALUE
38570af302Sopenharmony_ci} line_status;
39570af302Sopenharmony_ci
40570af302Sopenharmony_ci#define MAX_KEY_LEN 256
41570af302Sopenharmony_cistatic char g_key[MAX_KEY_LEN+1] = {0};
42570af302Sopenharmony_ci
43570af302Sopenharmony_cistatic char *config_key_join(const char *join, bool start)
44570af302Sopenharmony_ci{
45570af302Sopenharmony_ci    if (start) g_key[0] = 0;
46570af302Sopenharmony_ci    size_t cnt = MAX_KEY_LEN - strlen(g_key);
47570af302Sopenharmony_ci    return strncat(g_key, join, cnt);
48570af302Sopenharmony_ci}
49570af302Sopenharmony_ci
50570af302Sopenharmony_cistatic int default_error_callback(const char *format, ...)
51570af302Sopenharmony_ci{
52570af302Sopenharmony_ci    int ret = 0;
53570af302Sopenharmony_ci    va_list argptr;
54570af302Sopenharmony_ci    va_start(argptr, format);
55570af302Sopenharmony_ci    /* do not print
56570af302Sopenharmony_ci    ret = vfprintf(stderr, format, argptr);
57570af302Sopenharmony_ci    */
58570af302Sopenharmony_ci    va_end(argptr);
59570af302Sopenharmony_ci    return ret;
60570af302Sopenharmony_ci}
61570af302Sopenharmony_ci
62570af302Sopenharmony_cistatic int (*config_error_callback)(const char *, ...) = default_error_callback;
63570af302Sopenharmony_ci
64570af302Sopenharmony_cistatic void config_set_error_callback(int (*errback)(const char *, ...))
65570af302Sopenharmony_ci{
66570af302Sopenharmony_ci    if (errback) {
67570af302Sopenharmony_ci        config_error_callback = errback;
68570af302Sopenharmony_ci    } else {
69570af302Sopenharmony_ci        config_error_callback = default_error_callback;
70570af302Sopenharmony_ci    }
71570af302Sopenharmony_ci}
72570af302Sopenharmony_ci
73570af302Sopenharmony_cistatic line_status config_line(char *line, char *section, char *key, char *value)
74570af302Sopenharmony_ci{
75570af302Sopenharmony_ci    size_t len;
76570af302Sopenharmony_ci    char *split;
77570af302Sopenharmony_ci
78570af302Sopenharmony_ci    if ((len = strcspn(line, "#;")) == 0) {
79570af302Sopenharmony_ci        /* comment line */
80570af302Sopenharmony_ci        return LINE_COMMENT;
81570af302Sopenharmony_ci    }
82570af302Sopenharmony_ci    line[len] = 0;
83570af302Sopenharmony_ci    if ((len = strtrim(line)) == 0) {
84570af302Sopenharmony_ci        /* empty line */
85570af302Sopenharmony_ci         return LINE_EMPTY;
86570af302Sopenharmony_ci    }
87570af302Sopenharmony_ci    if (line[0] == '[' && line[len-1] == ']') {
88570af302Sopenharmony_ci        /* section name */
89570af302Sopenharmony_ci        memcpy(section, line+1, len-2);
90570af302Sopenharmony_ci        section[len-2] = 0;
91570af302Sopenharmony_ci        strtrim(section);
92570af302Sopenharmony_ci        return LINE_SECTION;
93570af302Sopenharmony_ci    }
94570af302Sopenharmony_ci    if (split = strchr(line, '=')) {
95570af302Sopenharmony_ci        /* key and value */
96570af302Sopenharmony_ci        size_t klen, vlen;
97570af302Sopenharmony_ci        klen = split - line;
98570af302Sopenharmony_ci        vlen = len - klen -1;
99570af302Sopenharmony_ci        if (klen > 0) memcpy(key, line, klen);
100570af302Sopenharmony_ci        if (vlen > 0) memcpy(value, split+1, vlen);
101570af302Sopenharmony_ci        key[klen] = 0;
102570af302Sopenharmony_ci        value[vlen] = 0;
103570af302Sopenharmony_ci        strtrim(key);
104570af302Sopenharmony_ci        strtrim(value);
105570af302Sopenharmony_ci        return LINE_VALUE;
106570af302Sopenharmony_ci    }
107570af302Sopenharmony_ci    return LINE_ERROR;
108570af302Sopenharmony_ci}
109570af302Sopenharmony_ci
110570af302Sopenharmony_ci#define SECTION_DEFAULT_SIZE   16
111570af302Sopenharmony_ci#define KV_DEFAULT_SIZE   64
112570af302Sopenharmony_ci
113570af302Sopenharmony_cistatic kvlist * kvlist_alloc(size_t size)
114570af302Sopenharmony_ci{
115570af302Sopenharmony_ci    kvlist *kvs;
116570af302Sopenharmony_ci
117570af302Sopenharmony_ci    if (size < KV_DEFAULT_SIZE) size = KV_DEFAULT_SIZE;
118570af302Sopenharmony_ci
119570af302Sopenharmony_ci    kvs = (kvlist *)__libc_calloc(1, sizeof *kvs);
120570af302Sopenharmony_ci    if (kvs) {
121570af302Sopenharmony_ci        kvs->key = (char **)__libc_calloc(size, sizeof *kvs->key);
122570af302Sopenharmony_ci        kvs->val = (char **)__libc_calloc(size, sizeof *kvs->val);
123570af302Sopenharmony_ci        if (kvs->key && kvs->val) {
124570af302Sopenharmony_ci            kvs->size = size;
125570af302Sopenharmony_ci        } else {
126570af302Sopenharmony_ci            __libc_free(kvs->key);
127570af302Sopenharmony_ci            __libc_free(kvs->val);
128570af302Sopenharmony_ci            __libc_free(kvs);
129570af302Sopenharmony_ci            kvs = NULL;
130570af302Sopenharmony_ci        }
131570af302Sopenharmony_ci    }
132570af302Sopenharmony_ci    return kvs;
133570af302Sopenharmony_ci}
134570af302Sopenharmony_ci
135570af302Sopenharmony_ciUT_STATIC void kvlist_realloc(kvlist *kvs)
136570af302Sopenharmony_ci{
137570af302Sopenharmony_ci    if (!kvs) return;
138570af302Sopenharmony_ci    size_t size = 2*kvs->size;
139570af302Sopenharmony_ci    if (size) {
140570af302Sopenharmony_ci        char **keys, **vals;
141570af302Sopenharmony_ci        keys = (char **)__libc_realloc(kvs->key, size * (sizeof *kvs->key));
142570af302Sopenharmony_ci        if (!keys) return;
143570af302Sopenharmony_ci        kvs->key = keys;
144570af302Sopenharmony_ci        vals = (char **)__libc_realloc(kvs->val, size * (sizeof *kvs->val));
145570af302Sopenharmony_ci        if (!vals) return;
146570af302Sopenharmony_ci        kvs->val = vals;
147570af302Sopenharmony_ci        kvs->size = size;
148570af302Sopenharmony_ci    }
149570af302Sopenharmony_ci
150570af302Sopenharmony_ci    return;
151570af302Sopenharmony_ci}
152570af302Sopenharmony_ci
153570af302Sopenharmony_cistatic void kvlist_free(kvlist *kvs)
154570af302Sopenharmony_ci{
155570af302Sopenharmony_ci    size_t i;
156570af302Sopenharmony_ci    if (!kvs) return;
157570af302Sopenharmony_ci    for (i=0; i<kvs->num; i++) {
158570af302Sopenharmony_ci        __libc_free(kvs->key[i]);
159570af302Sopenharmony_ci        __libc_free(kvs->val[i]);
160570af302Sopenharmony_ci    }
161570af302Sopenharmony_ci    __libc_free(kvs->key);
162570af302Sopenharmony_ci    __libc_free(kvs->val);
163570af302Sopenharmony_ci    __libc_free(kvs);
164570af302Sopenharmony_ci}
165570af302Sopenharmony_ci
166570af302Sopenharmony_cistatic section_list *sections_alloc(size_t size)
167570af302Sopenharmony_ci{
168570af302Sopenharmony_ci    section_list *sections;
169570af302Sopenharmony_ci    if (size < SECTION_DEFAULT_SIZE) size = SECTION_DEFAULT_SIZE;
170570af302Sopenharmony_ci
171570af302Sopenharmony_ci    sections = (section_list *)__libc_calloc(1, sizeof *sections);
172570af302Sopenharmony_ci
173570af302Sopenharmony_ci    if (sections) {
174570af302Sopenharmony_ci        sections->names = (char**)__libc_calloc(size, sizeof *sections->names);
175570af302Sopenharmony_ci        sections->kvs = (kvlist**)__libc_calloc(size, sizeof *sections->kvs);
176570af302Sopenharmony_ci        if (sections->names && sections->kvs) {
177570af302Sopenharmony_ci            sections->size = size;
178570af302Sopenharmony_ci        } else {
179570af302Sopenharmony_ci            __libc_free(sections->names);
180570af302Sopenharmony_ci            __libc_free(sections->kvs);
181570af302Sopenharmony_ci            __libc_free(sections);
182570af302Sopenharmony_ci            sections = NULL;
183570af302Sopenharmony_ci        }
184570af302Sopenharmony_ci    }
185570af302Sopenharmony_ci    return sections;
186570af302Sopenharmony_ci}
187570af302Sopenharmony_ci
188570af302Sopenharmony_ciUT_STATIC void sections_realloc(section_list *sections)
189570af302Sopenharmony_ci{
190570af302Sopenharmony_ci    if (!sections) return;
191570af302Sopenharmony_ci    size_t size = 2*sections->size;
192570af302Sopenharmony_ci    if (size) {
193570af302Sopenharmony_ci        char **names;
194570af302Sopenharmony_ci        kvlist **kvs;
195570af302Sopenharmony_ci        names = (char **)__libc_realloc(sections->names, size * (sizeof *sections->names));
196570af302Sopenharmony_ci        if (!names) return;
197570af302Sopenharmony_ci        sections->names = names;
198570af302Sopenharmony_ci        kvs = (kvlist **)__libc_realloc(sections->kvs, size * (sizeof *sections->kvs));
199570af302Sopenharmony_ci        if (!kvs) return;
200570af302Sopenharmony_ci        sections->kvs = kvs;
201570af302Sopenharmony_ci        sections->size = size;
202570af302Sopenharmony_ci    }
203570af302Sopenharmony_ci    return;
204570af302Sopenharmony_ci}
205570af302Sopenharmony_ci
206570af302Sopenharmony_cistatic void sections_free(section_list *sections)
207570af302Sopenharmony_ci{
208570af302Sopenharmony_ci    if (!sections) return;
209570af302Sopenharmony_ci    for (size_t i=0; i < sections->num; i++) {
210570af302Sopenharmony_ci        __libc_free(sections->names[i]);
211570af302Sopenharmony_ci        kvlist_free(sections->kvs[i]);
212570af302Sopenharmony_ci    }
213570af302Sopenharmony_ci    __libc_free(sections->names);
214570af302Sopenharmony_ci    __libc_free(sections->kvs);
215570af302Sopenharmony_ci    __libc_free(sections);
216570af302Sopenharmony_ci}
217570af302Sopenharmony_ci
218570af302Sopenharmony_cistatic void kvlist_set(kvlist *kvs, const char *key, const char *val)
219570af302Sopenharmony_ci{
220570af302Sopenharmony_ci    size_t i;
221570af302Sopenharmony_ci    if (!kvs||!key||!val) return;
222570af302Sopenharmony_ci
223570af302Sopenharmony_ci    for (i=0; i < kvs->num; i++) {
224570af302Sopenharmony_ci        if (!strcmp(kvs->key[i], key)) {
225570af302Sopenharmony_ci            break;
226570af302Sopenharmony_ci        }
227570af302Sopenharmony_ci    }
228570af302Sopenharmony_ci
229570af302Sopenharmony_ci    if (i < kvs->num) {
230570af302Sopenharmony_ci        char * v = ld_strdup(val);
231570af302Sopenharmony_ci        if (v) {
232570af302Sopenharmony_ci            __libc_free(kvs->val[i]);
233570af302Sopenharmony_ci            kvs->val[i] = v;
234570af302Sopenharmony_ci        }
235570af302Sopenharmony_ci        return;
236570af302Sopenharmony_ci    }
237570af302Sopenharmony_ci    if (kvs->num == kvs->size) {
238570af302Sopenharmony_ci        kvlist_realloc(kvs);
239570af302Sopenharmony_ci    }
240570af302Sopenharmony_ci    if (kvs->num < kvs->size) {
241570af302Sopenharmony_ci        kvs->key[kvs->num] = ld_strdup(key);
242570af302Sopenharmony_ci        kvs->val[kvs->num] = ld_strdup(val);
243570af302Sopenharmony_ci        if (kvs->key[kvs->num] && kvs->val[kvs->num]) {
244570af302Sopenharmony_ci            kvs->num++;
245570af302Sopenharmony_ci        } else {
246570af302Sopenharmony_ci            __libc_free(kvs->key[kvs->num]);
247570af302Sopenharmony_ci            __libc_free(kvs->val[kvs->num]);
248570af302Sopenharmony_ci        }
249570af302Sopenharmony_ci    }
250570af302Sopenharmony_ci    return;
251570af302Sopenharmony_ci}
252570af302Sopenharmony_ci
253570af302Sopenharmony_cistatic void sections_set(section_list *sections, const char *name, const char *key, const char *val)
254570af302Sopenharmony_ci{
255570af302Sopenharmony_ci    kvlist* kvs = NULL;
256570af302Sopenharmony_ci    if (!sections||!name||!key||!val) return;
257570af302Sopenharmony_ci
258570af302Sopenharmony_ci    for(size_t i=0; i < sections->num; i++) {
259570af302Sopenharmony_ci        if (!strcmp(sections->names[i], name)) {
260570af302Sopenharmony_ci            kvs = sections->kvs[i];
261570af302Sopenharmony_ci            break;
262570af302Sopenharmony_ci        }
263570af302Sopenharmony_ci    }
264570af302Sopenharmony_ci    if (kvs) {
265570af302Sopenharmony_ci        kvlist_set(kvs,key,val);
266570af302Sopenharmony_ci        return;
267570af302Sopenharmony_ci    }
268570af302Sopenharmony_ci
269570af302Sopenharmony_ci    if (sections->num == sections->size) {
270570af302Sopenharmony_ci       sections_realloc(sections);
271570af302Sopenharmony_ci    }
272570af302Sopenharmony_ci
273570af302Sopenharmony_ci    if (sections->num < sections->size) {
274570af302Sopenharmony_ci        kvs = kvlist_alloc(0);
275570af302Sopenharmony_ci        sections->names[sections->num] = ld_strdup(name);
276570af302Sopenharmony_ci        sections->kvs[sections->num] = kvs;
277570af302Sopenharmony_ci        if (sections->names[sections->num] && kvs) {
278570af302Sopenharmony_ci            sections->num++;
279570af302Sopenharmony_ci            kvlist_set(kvs,key,val);
280570af302Sopenharmony_ci        } else {
281570af302Sopenharmony_ci            __libc_free(sections->names[sections->num]);
282570af302Sopenharmony_ci            kvlist_free(kvs);
283570af302Sopenharmony_ci        }
284570af302Sopenharmony_ci    }
285570af302Sopenharmony_ci}
286570af302Sopenharmony_ci
287570af302Sopenharmony_cistatic section_list *config_load(const char *filepath)
288570af302Sopenharmony_ci{
289570af302Sopenharmony_ci    FILE *file;
290570af302Sopenharmony_ci    char line[MAX_LINE_SIZE+1];
291570af302Sopenharmony_ci    char section[MAX_LINE_SIZE+1];
292570af302Sopenharmony_ci    char key[MAX_LINE_SIZE+1];
293570af302Sopenharmony_ci    char val[MAX_LINE_SIZE+1];
294570af302Sopenharmony_ci
295570af302Sopenharmony_ci    size_t  len;
296570af302Sopenharmony_ci    int  lineno = 0;
297570af302Sopenharmony_ci
298570af302Sopenharmony_ci    section_list *sections;
299570af302Sopenharmony_ci
300570af302Sopenharmony_ci    if ((file = fopen(filepath, "r")) == NULL) {
301570af302Sopenharmony_ci        config_error_callback("config: cannot open %s\n", filepath);
302570af302Sopenharmony_ci        return NULL;
303570af302Sopenharmony_ci    }
304570af302Sopenharmony_ci
305570af302Sopenharmony_ci    sections = sections_alloc(0);
306570af302Sopenharmony_ci    if (!sections) {
307570af302Sopenharmony_ci        fclose(file);
308570af302Sopenharmony_ci        return NULL;
309570af302Sopenharmony_ci    }
310570af302Sopenharmony_ci
311570af302Sopenharmony_ci    memset(line, 0, sizeof line);
312570af302Sopenharmony_ci    memset(section, 0, sizeof section);
313570af302Sopenharmony_ci    memset(key, 0, sizeof key);
314570af302Sopenharmony_ci    memset(val, 0, sizeof val);
315570af302Sopenharmony_ci
316570af302Sopenharmony_ci    while (fgets(line, sizeof line, file)) {
317570af302Sopenharmony_ci        lineno++;
318570af302Sopenharmony_ci        len = strlen(line);
319570af302Sopenharmony_ci        if (len == 0) continue;
320570af302Sopenharmony_ci
321570af302Sopenharmony_ci        if (line[len-1]!='\n' && !feof(file)) {
322570af302Sopenharmony_ci            config_error_callback(
323570af302Sopenharmony_ci              "config: input line too long in %s (%d)\n", filepath, lineno);
324570af302Sopenharmony_ci            sections_free(sections);
325570af302Sopenharmony_ci            fclose(file);
326570af302Sopenharmony_ci            return NULL;
327570af302Sopenharmony_ci        }
328570af302Sopenharmony_ci
329570af302Sopenharmony_ci        if (line[len-1] == '\n') {
330570af302Sopenharmony_ci            line[len-1] = 0;
331570af302Sopenharmony_ci            len--;
332570af302Sopenharmony_ci        }
333570af302Sopenharmony_ci
334570af302Sopenharmony_ci        switch (config_line(line, section, key, val)) {
335570af302Sopenharmony_ci            case LINE_EMPTY:
336570af302Sopenharmony_ci            case LINE_COMMENT:
337570af302Sopenharmony_ci            case LINE_SECTION:
338570af302Sopenharmony_ci                break;
339570af302Sopenharmony_ci            case LINE_VALUE:
340570af302Sopenharmony_ci                sections_set(sections, section, key, val);
341570af302Sopenharmony_ci                break;
342570af302Sopenharmony_ci            case LINE_ERROR:
343570af302Sopenharmony_ci                config_error_callback(
344570af302Sopenharmony_ci                    "config: syntax error in %s (%d):\n-> %s\n",
345570af302Sopenharmony_ci                    filepath,
346570af302Sopenharmony_ci                    lineno,
347570af302Sopenharmony_ci                    line);
348570af302Sopenharmony_ci                break;
349570af302Sopenharmony_ci            default:
350570af302Sopenharmony_ci                break;
351570af302Sopenharmony_ci        }
352570af302Sopenharmony_ci    }
353570af302Sopenharmony_ci    fclose(file);
354570af302Sopenharmony_ci    return sections;
355570af302Sopenharmony_ci}
356570af302Sopenharmony_ci
357570af302Sopenharmony_cistatic ns_configor g_configor;
358570af302Sopenharmony_ci
359570af302Sopenharmony_ci/* const define */
360570af302Sopenharmony_ci#define CONFIG_DEFAULT_FILE "/etc/ld-musl-namespace-arm.ini"        /* default config file pathname */
361570af302Sopenharmony_ci#define SECTION_DIR_MAP "section.dir.map"   /* map of section and directory of app */
362570af302Sopenharmony_ci#define ATTR_NS_PREFIX "namespace"         /* prefix of namespace attribute */
363570af302Sopenharmony_ci#define ATTR_NS_ASAN "asan"                /* asan */
364570af302Sopenharmony_ci#define ATTR_NS_LIB_PATHS "lib.paths"         /* library search paths */
365570af302Sopenharmony_ci#define ATTR_NS_PERMITTED_PATHS "permitted.paths"         /* when separated, permitted dir paths of libs, including sub dirs */
366570af302Sopenharmony_ci#define ATTR_NS_INHERITS "inherits"          /* inherited namespace */
367570af302Sopenharmony_ci#define ATTR_NS_SEPARATED "separated"         /* if separated */
368570af302Sopenharmony_ci#define ATTR_ADDED_NSLIST "added.nslist"      /* all namespace names except default */
369570af302Sopenharmony_ci#define ATTR_NS_DEFAULT "default"           /* default namespace name */
370570af302Sopenharmony_ci#define ATTR_NS_ACQUIESCENCE "acquiescence"           /* acquiescence section name */
371570af302Sopenharmony_ci#define ATTR_NS_ALLOWED_LIBS "allowed.libs"      /* when separated, allowed library names */
372570af302Sopenharmony_ci#define ATTR_NS_INHERIT_SHARED_LIBS "shared.libs"      /* when inherited, shared library names */
373570af302Sopenharmony_ci#define SECTION_DIR_MAP_SYSTEM "system"      /* system path */
374570af302Sopenharmony_ci#define SECTION_DIR_MAP_ASAN_SYSTEM "asan_system"      /* asan system path */
375570af302Sopenharmony_ci
376570af302Sopenharmony_ci/* get key-value list of section */
377570af302Sopenharmony_cistatic kvlist *config_get_kvs(const char *sname)
378570af302Sopenharmony_ci{
379570af302Sopenharmony_ci    size_t  i;
380570af302Sopenharmony_ci    for (i=0; i<g_configor.sections->num; i++) {
381570af302Sopenharmony_ci        if (!strcmp(g_configor.sections->names[i], sname)) {
382570af302Sopenharmony_ci            return g_configor.sections->kvs[i];
383570af302Sopenharmony_ci        }
384570af302Sopenharmony_ci    }
385570af302Sopenharmony_ci    return NULL;
386570af302Sopenharmony_ci}
387570af302Sopenharmony_ci
388570af302Sopenharmony_ci/* get value by acquiescence */
389570af302Sopenharmony_cistatic char *config_get_value_by_acquiescence(kvlist *acquiescence_kvs, const char *key)
390570af302Sopenharmony_ci{
391570af302Sopenharmony_ci    if (!acquiescence_kvs) {
392570af302Sopenharmony_ci        return NULL;
393570af302Sopenharmony_ci    }
394570af302Sopenharmony_ci    size_t i;
395570af302Sopenharmony_ci    for (i=0; i<acquiescence_kvs->num; i++) {
396570af302Sopenharmony_ci        if (!strcmp(acquiescence_kvs->key[i], key)) {
397570af302Sopenharmony_ci            return acquiescence_kvs->val[i];
398570af302Sopenharmony_ci        }
399570af302Sopenharmony_ci    }
400570af302Sopenharmony_ci    return NULL;
401570af302Sopenharmony_ci}
402570af302Sopenharmony_ci
403570af302Sopenharmony_ci/* get value by acquiescence lib path */
404570af302Sopenharmony_cistatic char *config_get_acquiescence_lib_path(kvlist *acquiescence_kvs)
405570af302Sopenharmony_ci{
406570af302Sopenharmony_ci    if (!acquiescence_kvs) {
407570af302Sopenharmony_ci        return NULL;
408570af302Sopenharmony_ci    }
409570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
410570af302Sopenharmony_ci    config_key_join(".", false);
411570af302Sopenharmony_ci    config_key_join(ATTR_NS_DEFAULT, false);
412570af302Sopenharmony_ci    config_key_join(".", false);
413570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_LIB_PATHS, false);
414570af302Sopenharmony_ci    return config_get_value_by_acquiescence(acquiescence_kvs, key);
415570af302Sopenharmony_ci}
416570af302Sopenharmony_ci
417570af302Sopenharmony_ci/* get value by acquiescence asan lib path */
418570af302Sopenharmony_cistatic char *config_get_acquiescence_asan_lib_path(kvlist *acquiescence_kvs)
419570af302Sopenharmony_ci{
420570af302Sopenharmony_ci    if (!acquiescence_kvs) {
421570af302Sopenharmony_ci        return NULL;
422570af302Sopenharmony_ci    }
423570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
424570af302Sopenharmony_ci    config_key_join(".", false);
425570af302Sopenharmony_ci    config_key_join(ATTR_NS_DEFAULT, false);
426570af302Sopenharmony_ci    config_key_join(".", false);
427570af302Sopenharmony_ci    config_key_join(ATTR_NS_ASAN, false);
428570af302Sopenharmony_ci    config_key_join(".", false);
429570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_LIB_PATHS, false);
430570af302Sopenharmony_ci    return config_get_value_by_acquiescence(acquiescence_kvs, key);
431570af302Sopenharmony_ci}
432570af302Sopenharmony_ci
433570af302Sopenharmony_ci/* get value by key */
434570af302Sopenharmony_cistatic char *config_get_value(const char *key)
435570af302Sopenharmony_ci{
436570af302Sopenharmony_ci    if (!g_configor.kvs) {
437570af302Sopenharmony_ci        return NULL;
438570af302Sopenharmony_ci    }
439570af302Sopenharmony_ci    size_t i;
440570af302Sopenharmony_ci    for (i=0; i<g_configor.kvs->num; i++) {
441570af302Sopenharmony_ci        if (!strcmp(g_configor.kvs->key[i], key)) return g_configor.kvs->val[i];
442570af302Sopenharmony_ci    }
443570af302Sopenharmony_ci    return NULL;
444570af302Sopenharmony_ci}
445570af302Sopenharmony_ci
446570af302Sopenharmony_ci/* get library search paths */
447570af302Sopenharmony_cistatic char *config_get_lib_paths(const char *ns_name)
448570af302Sopenharmony_ci{
449570af302Sopenharmony_ci    if (ns_name == NULL) {
450570af302Sopenharmony_ci        return NULL;
451570af302Sopenharmony_ci    }
452570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
453570af302Sopenharmony_ci    config_key_join(".", false);
454570af302Sopenharmony_ci    config_key_join(ns_name, false);
455570af302Sopenharmony_ci    config_key_join(".", false);
456570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_LIB_PATHS, false);
457570af302Sopenharmony_ci    return config_get_value(key);
458570af302Sopenharmony_ci}
459570af302Sopenharmony_ci
460570af302Sopenharmony_ci/* get asan library search paths */
461570af302Sopenharmony_cistatic char *config_get_asan_lib_paths(const char *ns_name)
462570af302Sopenharmony_ci{
463570af302Sopenharmony_ci    if (ns_name == NULL) {
464570af302Sopenharmony_ci        return NULL;
465570af302Sopenharmony_ci    }
466570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
467570af302Sopenharmony_ci    config_key_join(".", false);
468570af302Sopenharmony_ci    config_key_join(ns_name, false);
469570af302Sopenharmony_ci    config_key_join(".", false);
470570af302Sopenharmony_ci    config_key_join(ATTR_NS_ASAN, false);
471570af302Sopenharmony_ci    config_key_join(".", false);
472570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_LIB_PATHS, false);
473570af302Sopenharmony_ci    return config_get_value(key);
474570af302Sopenharmony_ci}
475570af302Sopenharmony_ci
476570af302Sopenharmony_ci/* parse config, success 0, failure <0 */
477570af302Sopenharmony_cistatic int config_parse(const char *file_path, const char *exe_path)
478570af302Sopenharmony_ci{
479570af302Sopenharmony_ci    kvlist* dirkvs;
480570af302Sopenharmony_ci    kvlist* acquiescence_kvs;
481570af302Sopenharmony_ci    if (!exe_path) return -1;
482570af302Sopenharmony_ci    g_configor.exe_path = ld_strdup(exe_path);
483570af302Sopenharmony_ci    const char * fpath = CONFIG_DEFAULT_FILE;
484570af302Sopenharmony_ci    if (file_path) fpath = file_path;
485570af302Sopenharmony_ci    g_configor.file_path = ld_strdup(fpath);
486570af302Sopenharmony_ci    g_configor.sections = config_load(fpath);
487570af302Sopenharmony_ci
488570af302Sopenharmony_ci    if (!g_configor.sections) {
489570af302Sopenharmony_ci        LD_LOGD("config_parse load ini config fail!");
490570af302Sopenharmony_ci        return -2;
491570af302Sopenharmony_ci    }
492570af302Sopenharmony_ci    dirkvs = config_get_kvs(SECTION_DIR_MAP);
493570af302Sopenharmony_ci    acquiescence_kvs = config_get_kvs(ATTR_NS_ACQUIESCENCE);
494570af302Sopenharmony_ci    if (!dirkvs||!acquiescence_kvs) {
495570af302Sopenharmony_ci        LD_LOGD("config_parse get dirkvs or acquiescence_kvs fail!");
496570af302Sopenharmony_ci        return -3; /* no section directory map or acquiescence section found */
497570af302Sopenharmony_ci    }
498570af302Sopenharmony_ci    g_configor.config_sys_path = config_get_acquiescence_lib_path(acquiescence_kvs);
499570af302Sopenharmony_ci    g_configor.config_asan_sys_path = config_get_acquiescence_asan_lib_path(acquiescence_kvs);
500570af302Sopenharmony_ci    size_t i;
501570af302Sopenharmony_ci    char * sname = NULL;
502570af302Sopenharmony_ci    for (i=0; i<dirkvs->num; i++) {
503570af302Sopenharmony_ci       strlist * paths = strsplit(dirkvs->val[i], ":");
504570af302Sopenharmony_ci       if (paths) {
505570af302Sopenharmony_ci           size_t j;
506570af302Sopenharmony_ci           for (j=0; j<paths->num; j++) {
507570af302Sopenharmony_ci               if (!strcmp(paths->strs[j], exe_path)) break;
508570af302Sopenharmony_ci           }
509570af302Sopenharmony_ci           if (j<paths->num) sname = dirkvs->key[i];
510570af302Sopenharmony_ci        }
511570af302Sopenharmony_ci        strlist_free(paths);
512570af302Sopenharmony_ci        if (sname) break;
513570af302Sopenharmony_ci    }
514570af302Sopenharmony_ci    if (!sname) {
515570af302Sopenharmony_ci        /* No matched section found, use the default section. */
516570af302Sopenharmony_ci        sname = ATTR_NS_ACQUIESCENCE;
517570af302Sopenharmony_ci        LD_LOGD("config_parse no section found!");
518570af302Sopenharmony_ci    }
519570af302Sopenharmony_ci    if (!(g_configor.kvs = config_get_kvs(sname))) {
520570af302Sopenharmony_ci        LD_LOGD("config_parse no section key-value list found!");
521570af302Sopenharmony_ci        return -5;/* no section key-value list found */
522570af302Sopenharmony_ci    }
523570af302Sopenharmony_ci
524570af302Sopenharmony_ci    char *default_lib_paths = config_get_lib_paths(ATTR_NS_DEFAULT);
525570af302Sopenharmony_ci    if (default_lib_paths) {
526570af302Sopenharmony_ci        g_configor.config_sys_path = default_lib_paths;
527570af302Sopenharmony_ci    } else {
528570af302Sopenharmony_ci        LD_LOGW("config_parse get default lib paths fail! Config namespace default lib paths,please!");
529570af302Sopenharmony_ci    }
530570af302Sopenharmony_ci    char *default_asan_lib_paths = config_get_asan_lib_paths(ATTR_NS_DEFAULT);
531570af302Sopenharmony_ci    if (default_asan_lib_paths) {
532570af302Sopenharmony_ci        g_configor.config_asan_sys_path = default_asan_lib_paths;
533570af302Sopenharmony_ci    } else {
534570af302Sopenharmony_ci        LD_LOGW("config_parse get default asan lib paths fail! Config namespace default asan lib paths,please!");
535570af302Sopenharmony_ci    }
536570af302Sopenharmony_ci    return 0;
537570af302Sopenharmony_ci}
538570af302Sopenharmony_ci
539570af302Sopenharmony_ci/* get namespace names except default */
540570af302Sopenharmony_cistatic strlist *config_get_namespaces()
541570af302Sopenharmony_ci{
542570af302Sopenharmony_ci    char *key = config_key_join(ATTR_ADDED_NSLIST, true);
543570af302Sopenharmony_ci    char *val = config_get_value(key);
544570af302Sopenharmony_ci    return strsplit(val, ",");
545570af302Sopenharmony_ci}
546570af302Sopenharmony_ci
547570af302Sopenharmony_ci/* get permitted paths */
548570af302Sopenharmony_cistatic char *config_get_permitted_paths(const char *ns_name)
549570af302Sopenharmony_ci{
550570af302Sopenharmony_ci    if (ns_name == NULL) {
551570af302Sopenharmony_ci        return NULL;
552570af302Sopenharmony_ci    }
553570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
554570af302Sopenharmony_ci    config_key_join(".", false);
555570af302Sopenharmony_ci    config_key_join(ns_name, false);
556570af302Sopenharmony_ci    config_key_join(".", false);
557570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_PERMITTED_PATHS, false);
558570af302Sopenharmony_ci    return config_get_value(key);
559570af302Sopenharmony_ci}
560570af302Sopenharmony_ci
561570af302Sopenharmony_ci/* get asan permitted paths */
562570af302Sopenharmony_cistatic char *config_get_asan_permitted_paths(const char *ns_name)
563570af302Sopenharmony_ci{
564570af302Sopenharmony_ci    if (ns_name == NULL) {
565570af302Sopenharmony_ci        return NULL;
566570af302Sopenharmony_ci    }
567570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
568570af302Sopenharmony_ci    config_key_join(".", false);
569570af302Sopenharmony_ci    config_key_join(ns_name, false);
570570af302Sopenharmony_ci    config_key_join(".", false);
571570af302Sopenharmony_ci    config_key_join(ATTR_NS_ASAN, false);
572570af302Sopenharmony_ci    config_key_join(".", false);
573570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_PERMITTED_PATHS, false);
574570af302Sopenharmony_ci    return config_get_value(key);
575570af302Sopenharmony_ci}
576570af302Sopenharmony_ci/* get inherited namespace names */
577570af302Sopenharmony_cistatic strlist *config_get_inherits(const char *ns_name)
578570af302Sopenharmony_ci{
579570af302Sopenharmony_ci    if (ns_name == NULL) {
580570af302Sopenharmony_ci        return NULL;
581570af302Sopenharmony_ci    }
582570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
583570af302Sopenharmony_ci    config_key_join(".", false);
584570af302Sopenharmony_ci    config_key_join(ns_name, false);
585570af302Sopenharmony_ci    config_key_join(".", false);
586570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_INHERITS, false);
587570af302Sopenharmony_ci    char *val = config_get_value(key);
588570af302Sopenharmony_ci    return strsplit(val, ",");
589570af302Sopenharmony_ci}
590570af302Sopenharmony_ci/* get separated */
591570af302Sopenharmony_cistatic bool config_get_separated(const char *ns_name)
592570af302Sopenharmony_ci{
593570af302Sopenharmony_ci    if (ns_name == NULL) {
594570af302Sopenharmony_ci        return false;
595570af302Sopenharmony_ci    }
596570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
597570af302Sopenharmony_ci    config_key_join(".", false);
598570af302Sopenharmony_ci    config_key_join(ns_name, false);
599570af302Sopenharmony_ci    config_key_join(".", false);
600570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_SEPARATED, false);
601570af302Sopenharmony_ci    char *val = config_get_value(key);
602570af302Sopenharmony_ci    strlwc(val);
603570af302Sopenharmony_ci    if (val && !strcmp("true", val)) return true;
604570af302Sopenharmony_ci    return false;  /* default false */
605570af302Sopenharmony_ci}
606570af302Sopenharmony_ci
607570af302Sopenharmony_ci/* get allowed libs */
608570af302Sopenharmony_cistatic char *config_get_allowed_libs(const char *ns_name)
609570af302Sopenharmony_ci{
610570af302Sopenharmony_ci    if (ns_name == NULL) {
611570af302Sopenharmony_ci        return NULL;
612570af302Sopenharmony_ci    }
613570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
614570af302Sopenharmony_ci    config_key_join(".", false);
615570af302Sopenharmony_ci    config_key_join(ns_name, false);
616570af302Sopenharmony_ci    config_key_join(".", false);
617570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_ALLOWED_LIBS, false);
618570af302Sopenharmony_ci    return config_get_value(key);
619570af302Sopenharmony_ci}
620570af302Sopenharmony_ci/* get shared libs by inherited namespace */
621570af302Sopenharmony_cistatic char *config_get_inherit_shared_libs(const char *ns_name, const char *inherited_ns_name)
622570af302Sopenharmony_ci{
623570af302Sopenharmony_ci    if (ns_name == NULL || inherited_ns_name == NULL) {
624570af302Sopenharmony_ci        return NULL;
625570af302Sopenharmony_ci    }
626570af302Sopenharmony_ci    config_key_join(ATTR_NS_PREFIX, true);
627570af302Sopenharmony_ci    config_key_join(".", false);
628570af302Sopenharmony_ci    config_key_join(ns_name, false);
629570af302Sopenharmony_ci    config_key_join(".inherit.", false);
630570af302Sopenharmony_ci    config_key_join(inherited_ns_name, false);
631570af302Sopenharmony_ci    config_key_join(".", false);
632570af302Sopenharmony_ci    char *key = config_key_join(ATTR_NS_INHERIT_SHARED_LIBS, false);
633570af302Sopenharmony_ci    return config_get_value(key);
634570af302Sopenharmony_ci}
635570af302Sopenharmony_ci
636570af302Sopenharmony_ci/* The call time is after parse */
637570af302Sopenharmony_cistatic char *config_get_sys_paths(void)
638570af302Sopenharmony_ci{
639570af302Sopenharmony_ci    return g_configor.config_sys_path;
640570af302Sopenharmony_ci}
641570af302Sopenharmony_cistatic char *config_get_asan_sys_paths(void)
642570af302Sopenharmony_ci{
643570af302Sopenharmony_ci    return g_configor.config_asan_sys_path;
644570af302Sopenharmony_ci}
645570af302Sopenharmony_cins_configor *configor_init()
646570af302Sopenharmony_ci{
647570af302Sopenharmony_ci    memset(&g_configor, 0, sizeof g_configor);
648570af302Sopenharmony_ci    g_configor.set_error_callback = config_set_error_callback;
649570af302Sopenharmony_ci    g_configor.parse = config_parse;
650570af302Sopenharmony_ci    g_configor.get_namespaces = config_get_namespaces;
651570af302Sopenharmony_ci    g_configor.get_lib_paths = config_get_lib_paths;
652570af302Sopenharmony_ci    g_configor.get_asan_lib_paths = config_get_asan_lib_paths;
653570af302Sopenharmony_ci    g_configor.get_permitted_paths = config_get_permitted_paths;
654570af302Sopenharmony_ci    g_configor.get_asan_permitted_paths = config_get_asan_permitted_paths;
655570af302Sopenharmony_ci    g_configor.get_separated = config_get_separated;
656570af302Sopenharmony_ci    g_configor.get_inherits = config_get_inherits;
657570af302Sopenharmony_ci    g_configor.get_allowed_libs = config_get_allowed_libs;
658570af302Sopenharmony_ci    g_configor.get_inherit_shared_libs = config_get_inherit_shared_libs;
659570af302Sopenharmony_ci    g_configor.get_sys_paths = config_get_sys_paths;
660570af302Sopenharmony_ci    g_configor.get_asan_sys_paths = config_get_asan_sys_paths;
661570af302Sopenharmony_ci    g_configor.config_sys_path = NULL; // init it in config_parse.
662570af302Sopenharmony_ci    g_configor.config_asan_sys_path = NULL; // init it in config_parse.
663570af302Sopenharmony_ci    return &g_configor;
664570af302Sopenharmony_ci}
665570af302Sopenharmony_ci
666570af302Sopenharmony_civoid configor_free()
667570af302Sopenharmony_ci{
668570af302Sopenharmony_ci    if (g_configor.sections) {
669570af302Sopenharmony_ci        sections_free(g_configor.sections);
670570af302Sopenharmony_ci        g_configor.sections = NULL;
671570af302Sopenharmony_ci    }
672570af302Sopenharmony_ci    if (g_configor.file_path) {
673570af302Sopenharmony_ci        __libc_free(g_configor.file_path);
674570af302Sopenharmony_ci        g_configor.file_path = NULL;
675570af302Sopenharmony_ci    }
676570af302Sopenharmony_ci    if (g_configor.exe_path) {
677570af302Sopenharmony_ci        __libc_free(g_configor.exe_path);
678570af302Sopenharmony_ci        g_configor.exe_path = NULL;
679570af302Sopenharmony_ci    }
680570af302Sopenharmony_ci}