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 "ueventd_read_cfg.h"
17d9f0492fSopenharmony_ci
18d9f0492fSopenharmony_ci#include <ctype.h>
19d9f0492fSopenharmony_ci#include <string.h>
20d9f0492fSopenharmony_ci#include <stdbool.h>
21d9f0492fSopenharmony_ci#include <stdlib.h>
22d9f0492fSopenharmony_ci#include <unistd.h>
23d9f0492fSopenharmony_ci#include <errno.h>
24d9f0492fSopenharmony_ci#include <fcntl.h>
25d9f0492fSopenharmony_ci#include <sys/stat.h>
26d9f0492fSopenharmony_ci#include "init_utils.h"
27d9f0492fSopenharmony_ci#include "list.h"
28d9f0492fSopenharmony_ci#include "ueventd_utils.h"
29d9f0492fSopenharmony_ci#include "securec.h"
30d9f0492fSopenharmony_ci#define INIT_LOG_TAG "ueventd"
31d9f0492fSopenharmony_ci#include "init_log.h"
32d9f0492fSopenharmony_ci
33d9f0492fSopenharmony_ci// default item count in config files
34d9f0492fSopenharmony_ci#define DEFAULTITEMCOUNT (50)
35d9f0492fSopenharmony_ci#define MAX_CONFIGURE_SIZE (1024 * 1024 * 16)
36d9f0492fSopenharmony_ci
37d9f0492fSopenharmony_citypedef enum SECTION {
38d9f0492fSopenharmony_ci    SECTION_INVALID = -1,
39d9f0492fSopenharmony_ci    SECTION_DEVICE = 0,
40d9f0492fSopenharmony_ci    SECTION_SYSFS,
41d9f0492fSopenharmony_ci    SECTION_FIRMWARE
42d9f0492fSopenharmony_ci} SECTION;
43d9f0492fSopenharmony_ci
44d9f0492fSopenharmony_citypedef int (*ParseConfigFunc)(char *);
45d9f0492fSopenharmony_citypedef struct FunctionMapper {
46d9f0492fSopenharmony_ci    const char *name;
47d9f0492fSopenharmony_ci    ParseConfigFunc func;
48d9f0492fSopenharmony_ci} FUNCTIONMAPPER;
49d9f0492fSopenharmony_ci
50d9f0492fSopenharmony_cistruct ListNode g_devices = {
51d9f0492fSopenharmony_ci    .next = &g_devices,
52d9f0492fSopenharmony_ci    .prev = &g_devices,
53d9f0492fSopenharmony_ci};
54d9f0492fSopenharmony_ci
55d9f0492fSopenharmony_cistruct ListNode g_sysDevices = {
56d9f0492fSopenharmony_ci    .next = &g_sysDevices,
57d9f0492fSopenharmony_ci    .prev = &g_sysDevices,
58d9f0492fSopenharmony_ci};
59d9f0492fSopenharmony_ci
60d9f0492fSopenharmony_cistruct ListNode g_firmwares = {
61d9f0492fSopenharmony_ci    .next = &g_firmwares,
62d9f0492fSopenharmony_ci    .prev = &g_firmwares,
63d9f0492fSopenharmony_ci};
64d9f0492fSopenharmony_ci
65d9f0492fSopenharmony_cistatic int ParseDeviceConfig(char *p)
66d9f0492fSopenharmony_ci{
67d9f0492fSopenharmony_ci    INIT_LOGV("Parse device config info: %s", p);
68d9f0492fSopenharmony_ci    char **items = NULL;
69d9f0492fSopenharmony_ci    int count = -1;
70d9f0492fSopenharmony_ci    // format: <device node> <mode> <uid> <gid> <parameter>
71d9f0492fSopenharmony_ci    const int expectedCount = 5;
72d9f0492fSopenharmony_ci
73d9f0492fSopenharmony_ci    INIT_CHECK_ONLY_ELOG(!INVALIDSTRING(p), "Invalid argument");
74d9f0492fSopenharmony_ci    items = SplitStringExt(p, " ", &count, expectedCount);
75d9f0492fSopenharmony_ci    if ((count != expectedCount) && (count != expectedCount - 1)) {
76d9f0492fSopenharmony_ci        INIT_LOGE("Ignore invalid item: %s", p);
77d9f0492fSopenharmony_ci        FreeStringVector(items, count);
78d9f0492fSopenharmony_ci        return 0;
79d9f0492fSopenharmony_ci    }
80d9f0492fSopenharmony_ci
81d9f0492fSopenharmony_ci    struct DeviceUdevConf *config = calloc(1, sizeof(struct DeviceUdevConf));
82d9f0492fSopenharmony_ci    if (config == NULL) {
83d9f0492fSopenharmony_ci        errno = ENOMEM;
84d9f0492fSopenharmony_ci        FreeStringVector(items, count);
85d9f0492fSopenharmony_ci        return -1;
86d9f0492fSopenharmony_ci    }
87d9f0492fSopenharmony_ci    config->name = strdup(items[0]); // device node
88d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(config->name != NULL, FreeStringVector(items, count);
89d9f0492fSopenharmony_ci                     free(config); return -1, "failed dup config name");
90d9f0492fSopenharmony_ci    errno = 0;
91d9f0492fSopenharmony_ci    config->mode = strtoul(items[1], NULL, OCTAL_BASE); // mode
92d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(errno == 0, config->mode = DEVMODE,
93d9f0492fSopenharmony_ci        "Invalid mode in config file for device node %s. use default mode", config->name);
94d9f0492fSopenharmony_ci    config->uid = (uid_t)DecodeUid(items[2]); // uid
95d9f0492fSopenharmony_ci    config->gid = (gid_t)DecodeGid(items[3]); // gid
96d9f0492fSopenharmony_ci    if (count == expectedCount) {
97d9f0492fSopenharmony_ci        config->parameter = strdup(items[4]); // device parameter
98d9f0492fSopenharmony_ci        INIT_ERROR_CHECK(config->parameter != NULL, FreeStringVector(items, count);
99d9f0492fSopenharmony_ci                         free((void*)config->name); free(config); return -1, "failed dup parameter");
100d9f0492fSopenharmony_ci    } else {
101d9f0492fSopenharmony_ci        config->parameter = NULL;
102d9f0492fSopenharmony_ci    }
103d9f0492fSopenharmony_ci    OH_ListInit(&config->paramNode);
104d9f0492fSopenharmony_ci    OH_ListAddTail(&g_devices, &config->list);
105d9f0492fSopenharmony_ci    FreeStringVector(items, count);
106d9f0492fSopenharmony_ci    return 0;
107d9f0492fSopenharmony_ci}
108d9f0492fSopenharmony_ci
109d9f0492fSopenharmony_cistatic int ParseSysfsConfig(char *p)
110d9f0492fSopenharmony_ci{
111d9f0492fSopenharmony_ci    INIT_LOGV("Parse sysfs config info: %s", p);
112d9f0492fSopenharmony_ci    char **items = NULL;
113d9f0492fSopenharmony_ci    int count = -1;
114d9f0492fSopenharmony_ci    // format: <syspath> <attribute> <mode> <uid> <gid>
115d9f0492fSopenharmony_ci    const int expectedCount = 5;
116d9f0492fSopenharmony_ci
117d9f0492fSopenharmony_ci    INIT_CHECK_ONLY_ELOG(!INVALIDSTRING(p), "Invalid argument");
118d9f0492fSopenharmony_ci    items = SplitStringExt(p, " ", &count, expectedCount);
119d9f0492fSopenharmony_ci    if (count != expectedCount) {
120d9f0492fSopenharmony_ci        INIT_LOGE("Ignore invalid item: %s", p);
121d9f0492fSopenharmony_ci        FreeStringVector(items, count);
122d9f0492fSopenharmony_ci        return 0;
123d9f0492fSopenharmony_ci    }
124d9f0492fSopenharmony_ci    struct SysUdevConf *config = calloc(1, sizeof(struct SysUdevConf));
125d9f0492fSopenharmony_ci    if (config == NULL) {
126d9f0492fSopenharmony_ci        errno = ENOMEM;
127d9f0492fSopenharmony_ci        FreeStringVector(items, count);
128d9f0492fSopenharmony_ci        return -1;
129d9f0492fSopenharmony_ci    }
130d9f0492fSopenharmony_ci    config->sysPath = strdup(items[0]); // sys path
131d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(config->sysPath != NULL, FreeStringVector(items, count);
132d9f0492fSopenharmony_ci                     free(config); return -1, "failed to dup syspath");
133d9f0492fSopenharmony_ci    config->attr = strdup(items[1]);  // attribute
134d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(config->attr != NULL, FreeStringVector(items, count);
135d9f0492fSopenharmony_ci                     free((void*)config->sysPath); free(config); return -1, "failed to dup attr");
136d9f0492fSopenharmony_ci    errno = 0;
137d9f0492fSopenharmony_ci    config->mode = strtoul(items[2], NULL, OCTAL_BASE); // mode
138d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(errno == 0, config->mode = DEVMODE,
139d9f0492fSopenharmony_ci        "Invalid mode in config file for sys path %s. use default mode", config->sysPath);
140d9f0492fSopenharmony_ci    config->uid = (uid_t)DecodeUid(items[3]); // uid
141d9f0492fSopenharmony_ci    config->gid = (gid_t)DecodeGid(items[4]); // gid
142d9f0492fSopenharmony_ci    OH_ListAddTail(&g_sysDevices, &config->list);
143d9f0492fSopenharmony_ci    FreeStringVector(items, count);
144d9f0492fSopenharmony_ci    return 0;
145d9f0492fSopenharmony_ci}
146d9f0492fSopenharmony_ci
147d9f0492fSopenharmony_cistatic int ParseFirmwareConfig(char *p)
148d9f0492fSopenharmony_ci{
149d9f0492fSopenharmony_ci    INIT_LOGV("Parse firmware config info: %s", p);
150d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(!INVALIDSTRING(p), return -1, "Invalid argument");
151d9f0492fSopenharmony_ci
152d9f0492fSopenharmony_ci    // Sanity checks
153d9f0492fSopenharmony_ci    struct stat st = {};
154d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(stat(p, &st) == 0, return -1, "Invalid firmware file: %s, err = %d", p, errno);
155d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(S_ISDIR(st.st_mode), return -1, "Expect directory in firmware config");
156d9f0492fSopenharmony_ci    struct FirmwareUdevConf *config = calloc(1, sizeof(struct FirmwareUdevConf));
157d9f0492fSopenharmony_ci    INIT_CHECK(config != NULL, errno = ENOMEM;
158d9f0492fSopenharmony_ci        return -1);
159d9f0492fSopenharmony_ci    config->fmPath = strdup(p);
160d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(config->fmPath != NULL, free(config); return -1, "failed to dup fmpath");
161d9f0492fSopenharmony_ci    OH_ListAddTail(&g_firmwares, &config->list);
162d9f0492fSopenharmony_ci    return 0;
163d9f0492fSopenharmony_ci}
164d9f0492fSopenharmony_ci
165d9f0492fSopenharmony_cistatic SECTION GetSection(const char *section)
166d9f0492fSopenharmony_ci{
167d9f0492fSopenharmony_ci    INIT_CHECK_RETURN_VALUE(!INVALIDSTRING(section), SECTION_INVALID);
168d9f0492fSopenharmony_ci    if (STRINGEQUAL(section, "device")) {
169d9f0492fSopenharmony_ci        return SECTION_DEVICE;
170d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(section, "sysfs")) {
171d9f0492fSopenharmony_ci        return SECTION_SYSFS;
172d9f0492fSopenharmony_ci    } else if (STRINGEQUAL(section, "firmware")) {
173d9f0492fSopenharmony_ci        return SECTION_FIRMWARE;
174d9f0492fSopenharmony_ci    } else {
175d9f0492fSopenharmony_ci        return SECTION_INVALID;
176d9f0492fSopenharmony_ci    }
177d9f0492fSopenharmony_ci}
178d9f0492fSopenharmony_ci
179d9f0492fSopenharmony_cistatic const FUNCTIONMAPPER funcMapper[3] = {
180d9f0492fSopenharmony_ci    {"device", ParseDeviceConfig},
181d9f0492fSopenharmony_ci    {"sysfs", ParseSysfsConfig},
182d9f0492fSopenharmony_ci    {"firmware", ParseFirmwareConfig}
183d9f0492fSopenharmony_ci};
184d9f0492fSopenharmony_ci
185d9f0492fSopenharmony_ciParseConfigFunc callback;
186d9f0492fSopenharmony_ciint ParseUeventConfig(char *buffer)
187d9f0492fSopenharmony_ci{
188d9f0492fSopenharmony_ci    char *section = NULL;
189d9f0492fSopenharmony_ci    char *right = NULL;
190d9f0492fSopenharmony_ci    char *p = buffer;
191d9f0492fSopenharmony_ci    SECTION type;
192d9f0492fSopenharmony_ci
193d9f0492fSopenharmony_ci    INIT_CHECK_RETURN_VALUE(!INVALIDSTRING(buffer), -1);
194d9f0492fSopenharmony_ci    if (*p == '[') {
195d9f0492fSopenharmony_ci        p++;
196d9f0492fSopenharmony_ci        if ((right = strchr(p, ']')) == NULL) {
197d9f0492fSopenharmony_ci            INIT_LOGE("Invalid line \"%s\", miss ']'", buffer);
198d9f0492fSopenharmony_ci            return -1;
199d9f0492fSopenharmony_ci        }
200d9f0492fSopenharmony_ci        *right = '\0'; // Replace ']' with '\0';
201d9f0492fSopenharmony_ci        section = p;
202d9f0492fSopenharmony_ci        INIT_LOGV("section is [%s]", section);
203d9f0492fSopenharmony_ci        if ((type = GetSection(section)) == SECTION_INVALID) {
204d9f0492fSopenharmony_ci            INIT_LOGE("Invalid section \" %s \"", section);
205d9f0492fSopenharmony_ci            callback = NULL; // reset callback
206d9f0492fSopenharmony_ci            return -1;
207d9f0492fSopenharmony_ci        }
208d9f0492fSopenharmony_ci        callback = funcMapper[type].func;
209d9f0492fSopenharmony_ci        return 0;
210d9f0492fSopenharmony_ci    }
211d9f0492fSopenharmony_ci    return (callback != NULL) ? callback(p) : -1;
212d9f0492fSopenharmony_ci}
213d9f0492fSopenharmony_ci
214d9f0492fSopenharmony_cistatic void DoUeventConfigParse(char *buffer, size_t length)
215d9f0492fSopenharmony_ci{
216d9f0492fSopenharmony_ci    char **items = NULL;
217d9f0492fSopenharmony_ci    int count = -1;
218d9f0492fSopenharmony_ci    const int maxItemCount = DEFAULTITEMCOUNT;
219d9f0492fSopenharmony_ci
220d9f0492fSopenharmony_ci    items = SplitStringExt(buffer, "\n", &count, maxItemCount);
221d9f0492fSopenharmony_ci    INIT_LOGV("Dump items count = %d", count);
222d9f0492fSopenharmony_ci    for (int i = 0; i < count; i++) {
223d9f0492fSopenharmony_ci        char *p = items[i];
224d9f0492fSopenharmony_ci        // Skip lead white space
225d9f0492fSopenharmony_ci        while (isspace(*p)) {
226d9f0492fSopenharmony_ci            p++;
227d9f0492fSopenharmony_ci        }
228d9f0492fSopenharmony_ci
229d9f0492fSopenharmony_ci        // Skip comment or empty line
230d9f0492fSopenharmony_ci        if (*p == '\0' || *p == '#') {
231d9f0492fSopenharmony_ci            continue;
232d9f0492fSopenharmony_ci        }
233d9f0492fSopenharmony_ci        int rc = ParseUeventConfig(p);
234d9f0492fSopenharmony_ci        if (rc < 0) {
235d9f0492fSopenharmony_ci            INIT_LOGE("Parse uevent config from %s failed", p);
236d9f0492fSopenharmony_ci        }
237d9f0492fSopenharmony_ci    }
238d9f0492fSopenharmony_ci    // release memory
239d9f0492fSopenharmony_ci    FreeStringVector(items, count);
240d9f0492fSopenharmony_ci}
241d9f0492fSopenharmony_ci
242d9f0492fSopenharmony_civoid ParseUeventdConfigFile(const char *file)
243d9f0492fSopenharmony_ci{
244d9f0492fSopenharmony_ci    INIT_CHECK_ONLY_RETURN(!INVALIDSTRING(file));
245d9f0492fSopenharmony_ci    char *config = GetRealPath(file);
246d9f0492fSopenharmony_ci    INIT_CHECK_ONLY_RETURN(config != NULL);
247d9f0492fSopenharmony_ci    int fd = open(config, O_RDONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
248d9f0492fSopenharmony_ci    free(config);
249d9f0492fSopenharmony_ci    INIT_ERROR_CHECK(fd >= 0, return, "Read from %s failed", file);
250d9f0492fSopenharmony_ci
251d9f0492fSopenharmony_ci    struct stat st;
252d9f0492fSopenharmony_ci    if (fstat(fd, &st) < 0) {
253d9f0492fSopenharmony_ci        INIT_LOGE("Failed to get file stat. err = %d", errno);
254d9f0492fSopenharmony_ci        close(fd);
255d9f0492fSopenharmony_ci        return;
256d9f0492fSopenharmony_ci    }
257d9f0492fSopenharmony_ci
258d9f0492fSopenharmony_ci    // st_size should never be less than 0
259d9f0492fSopenharmony_ci    if (st.st_size < 0 || st.st_size > MAX_CONFIGURE_SIZE) {
260d9f0492fSopenharmony_ci        INIT_LOGE("Invalid configure file with size");
261d9f0492fSopenharmony_ci        close(fd);
262d9f0492fSopenharmony_ci        return;
263d9f0492fSopenharmony_ci    }
264d9f0492fSopenharmony_ci    size_t size = (size_t)st.st_size;
265d9f0492fSopenharmony_ci    char *buffer = malloc(size + 1);
266d9f0492fSopenharmony_ci    if (buffer == NULL) {
267d9f0492fSopenharmony_ci        INIT_LOGE("Failed to malloc memory. err = %d", errno);
268d9f0492fSopenharmony_ci        close(fd);
269d9f0492fSopenharmony_ci        return;
270d9f0492fSopenharmony_ci    }
271d9f0492fSopenharmony_ci
272d9f0492fSopenharmony_ci    if (read(fd, buffer, size) != (ssize_t)size) {
273d9f0492fSopenharmony_ci        INIT_LOGE("Read from file %s failed. err = %d", file, errno);
274d9f0492fSopenharmony_ci        free(buffer);
275d9f0492fSopenharmony_ci        buffer = NULL;
276d9f0492fSopenharmony_ci        close(fd);
277d9f0492fSopenharmony_ci        return;
278d9f0492fSopenharmony_ci    }
279d9f0492fSopenharmony_ci
280d9f0492fSopenharmony_ci    buffer[size] = '\0';
281d9f0492fSopenharmony_ci    DoUeventConfigParse(buffer, size);
282d9f0492fSopenharmony_ci    free(buffer);
283d9f0492fSopenharmony_ci    buffer = NULL;
284d9f0492fSopenharmony_ci    close(fd);
285d9f0492fSopenharmony_ci}
286d9f0492fSopenharmony_ci
287d9f0492fSopenharmony_ci// support '*' to match all characters
288d9f0492fSopenharmony_ci// '?' match one character.
289d9f0492fSopenharmony_cibool IsMatch(const char *target, const char *pattern)
290d9f0492fSopenharmony_ci{
291d9f0492fSopenharmony_ci    INIT_CHECK_RETURN_VALUE(target != NULL, false);
292d9f0492fSopenharmony_ci    INIT_CHECK_RETURN_VALUE(pattern != NULL, true);
293d9f0492fSopenharmony_ci
294d9f0492fSopenharmony_ci    const char *t = target;
295d9f0492fSopenharmony_ci    const char *p = pattern;
296d9f0492fSopenharmony_ci    const char *plast = NULL;
297d9f0492fSopenharmony_ci    bool reMatch = false;
298d9f0492fSopenharmony_ci    while (*t != '\0') {
299d9f0492fSopenharmony_ci        if (*t == *p) {
300d9f0492fSopenharmony_ci            t++;
301d9f0492fSopenharmony_ci            p++;
302d9f0492fSopenharmony_ci            continue;
303d9f0492fSopenharmony_ci        }
304d9f0492fSopenharmony_ci
305d9f0492fSopenharmony_ci        // Match one character.
306d9f0492fSopenharmony_ci        if (*p == '?') {
307d9f0492fSopenharmony_ci            p++;
308d9f0492fSopenharmony_ci            t++;
309d9f0492fSopenharmony_ci            continue;
310d9f0492fSopenharmony_ci        }
311d9f0492fSopenharmony_ci
312d9f0492fSopenharmony_ci        if (*p == '\0') {
313d9f0492fSopenharmony_ci            return reMatch;
314d9f0492fSopenharmony_ci        }
315d9f0492fSopenharmony_ci
316d9f0492fSopenharmony_ci        if (*p == '*') {
317d9f0492fSopenharmony_ci            reMatch = true;
318d9f0492fSopenharmony_ci            // Met '*', record where we will start over.
319d9f0492fSopenharmony_ci            // plast point to next character that we will compare it again.
320d9f0492fSopenharmony_ci            plast = ++p;
321d9f0492fSopenharmony_ci            t++;
322d9f0492fSopenharmony_ci            continue;
323d9f0492fSopenharmony_ci        }
324d9f0492fSopenharmony_ci
325d9f0492fSopenharmony_ci        if (reMatch) {
326d9f0492fSopenharmony_ci            // Start over.
327d9f0492fSopenharmony_ci            p = plast;
328d9f0492fSopenharmony_ci            t++;
329d9f0492fSopenharmony_ci        } else {
330d9f0492fSopenharmony_ci            return false;
331d9f0492fSopenharmony_ci        }
332d9f0492fSopenharmony_ci    }
333d9f0492fSopenharmony_ci
334d9f0492fSopenharmony_ci    while (*p == '*') {
335d9f0492fSopenharmony_ci        p++;
336d9f0492fSopenharmony_ci    }
337d9f0492fSopenharmony_ci    return (*p == '\0');
338d9f0492fSopenharmony_ci}
339d9f0492fSopenharmony_ci
340d9f0492fSopenharmony_cistruct DeviceUdevConf *GetDeviceUdevConfByDevNode(const char *devNode)
341d9f0492fSopenharmony_ci{
342d9f0492fSopenharmony_ci    if (INVALIDSTRING(devNode)) {
343d9f0492fSopenharmony_ci        return NULL;
344d9f0492fSopenharmony_ci    }
345d9f0492fSopenharmony_ci
346d9f0492fSopenharmony_ci    struct ListNode *node = NULL;
347d9f0492fSopenharmony_ci    if (!ListEmpty(g_devices)) {
348d9f0492fSopenharmony_ci        ForEachListEntry(&g_devices, node) {
349d9f0492fSopenharmony_ci            struct DeviceUdevConf *config = ListEntry(node, struct DeviceUdevConf, list);
350d9f0492fSopenharmony_ci            if (IsMatch(devNode, config->name)) {
351d9f0492fSopenharmony_ci                return config;
352d9f0492fSopenharmony_ci            }
353d9f0492fSopenharmony_ci        }
354d9f0492fSopenharmony_ci    }
355d9f0492fSopenharmony_ci
356d9f0492fSopenharmony_ci    return NULL;
357d9f0492fSopenharmony_ci}
358d9f0492fSopenharmony_ci
359d9f0492fSopenharmony_ciint GetDeviceNodePermissions(const char *devNode, uid_t *uid, gid_t *gid, mode_t *mode)
360d9f0492fSopenharmony_ci{
361d9f0492fSopenharmony_ci    if (INVALIDSTRING(devNode)) {
362d9f0492fSopenharmony_ci        return -1;
363d9f0492fSopenharmony_ci    }
364d9f0492fSopenharmony_ci
365d9f0492fSopenharmony_ci    struct ListNode *node = NULL;
366d9f0492fSopenharmony_ci    if (!ListEmpty(g_devices)) {
367d9f0492fSopenharmony_ci        ForEachListEntry(&g_devices, node) {
368d9f0492fSopenharmony_ci            struct DeviceUdevConf *config = ListEntry(node, struct DeviceUdevConf, list);
369d9f0492fSopenharmony_ci            if (IsMatch(devNode, config->name)) {
370d9f0492fSopenharmony_ci                *uid = config->uid;
371d9f0492fSopenharmony_ci                *gid = config->gid;
372d9f0492fSopenharmony_ci                *mode = config->mode;
373d9f0492fSopenharmony_ci                return 0;
374d9f0492fSopenharmony_ci            }
375d9f0492fSopenharmony_ci        }
376d9f0492fSopenharmony_ci    }
377d9f0492fSopenharmony_ci    return -1;
378d9f0492fSopenharmony_ci}
379d9f0492fSopenharmony_ci
380d9f0492fSopenharmony_civoid ChangeSysAttributePermissions(const char *sysPath)
381d9f0492fSopenharmony_ci{
382d9f0492fSopenharmony_ci    if (INVALIDSTRING(sysPath)) {
383d9f0492fSopenharmony_ci        return;
384d9f0492fSopenharmony_ci    }
385d9f0492fSopenharmony_ci
386d9f0492fSopenharmony_ci    struct ListNode *node = NULL;
387d9f0492fSopenharmony_ci    struct SysUdevConf *config = NULL;
388d9f0492fSopenharmony_ci    int matched = 0;
389d9f0492fSopenharmony_ci    if (!ListEmpty(g_sysDevices)) {
390d9f0492fSopenharmony_ci        ForEachListEntry(&g_sysDevices, node) {
391d9f0492fSopenharmony_ci            config = ListEntry(node, struct SysUdevConf, list);
392d9f0492fSopenharmony_ci            if (STRINGEQUAL(config->sysPath, sysPath)) {
393d9f0492fSopenharmony_ci                matched = 1;
394d9f0492fSopenharmony_ci                break;
395d9f0492fSopenharmony_ci            }
396d9f0492fSopenharmony_ci        }
397d9f0492fSopenharmony_ci    }
398d9f0492fSopenharmony_ci
399d9f0492fSopenharmony_ci    if (matched == 0) {
400d9f0492fSopenharmony_ci        return;
401d9f0492fSopenharmony_ci    }
402d9f0492fSopenharmony_ci    char sysAttr[SYSPATH_SIZE] = {};
403d9f0492fSopenharmony_ci    if (snprintf_s(sysAttr, SYSPATH_SIZE, SYSPATH_SIZE - 1, "/sys%s/%s", config->sysPath, config->attr) == -1) {
404d9f0492fSopenharmony_ci        INIT_LOGE("Failed to build sys attribute for sys path %s, attr: %s", config->sysPath, config->attr);
405d9f0492fSopenharmony_ci        return;
406d9f0492fSopenharmony_ci    }
407d9f0492fSopenharmony_ci    if (chown(sysAttr, config->uid, config->gid) < 0) {
408d9f0492fSopenharmony_ci        INIT_LOGE("chown for file %s failed, err = %d", sysAttr, errno);
409d9f0492fSopenharmony_ci    }
410d9f0492fSopenharmony_ci
411d9f0492fSopenharmony_ci    if (chmod(sysAttr, config->mode) < 0) {
412d9f0492fSopenharmony_ci        INIT_LOGE("[uevent][error] chmod for file %s failed, err = %d", sysAttr, errno);
413d9f0492fSopenharmony_ci    }
414d9f0492fSopenharmony_ci}
415d9f0492fSopenharmony_ci
416d9f0492fSopenharmony_cistatic void FreeDeviceConfig(ListNode *node)
417d9f0492fSopenharmony_ci{
418d9f0492fSopenharmony_ci    struct DeviceUdevConf *config = ListEntry(node, struct DeviceUdevConf, list);
419d9f0492fSopenharmony_ci    free((void *)config->name);
420d9f0492fSopenharmony_ci    free((void *)config->parameter);
421d9f0492fSopenharmony_ci    OH_ListRemove(&config->paramNode);
422d9f0492fSopenharmony_ci    free(config);
423d9f0492fSopenharmony_ci}
424d9f0492fSopenharmony_ci
425d9f0492fSopenharmony_cistatic void FreeSysUdevConf(ListNode *node)
426d9f0492fSopenharmony_ci{
427d9f0492fSopenharmony_ci    struct SysUdevConf *config = ListEntry(node, struct SysUdevConf, list);
428d9f0492fSopenharmony_ci    free((void *)config->sysPath);
429d9f0492fSopenharmony_ci    free((void *)config->attr);
430d9f0492fSopenharmony_ci    free(config);
431d9f0492fSopenharmony_ci}
432d9f0492fSopenharmony_ci
433d9f0492fSopenharmony_cistatic void FreeFirmwareUdevConf(ListNode *node)
434d9f0492fSopenharmony_ci{
435d9f0492fSopenharmony_ci    struct FirmwareUdevConf *config = ListEntry(node, struct FirmwareUdevConf, list);
436d9f0492fSopenharmony_ci    free((void *)config->fmPath);
437d9f0492fSopenharmony_ci    free(config);
438d9f0492fSopenharmony_ci}
439d9f0492fSopenharmony_ci
440d9f0492fSopenharmony_civoid CloseUeventConfig(void)
441d9f0492fSopenharmony_ci{
442d9f0492fSopenharmony_ci    OH_ListRemoveAll(&g_devices, FreeDeviceConfig);
443d9f0492fSopenharmony_ci    OH_ListRemoveAll(&g_sysDevices, FreeSysUdevConf);
444d9f0492fSopenharmony_ci    OH_ListRemoveAll(&g_firmwares, FreeFirmwareUdevConf);
445d9f0492fSopenharmony_ci}